Merge pull request #7102 from Icinga/feature/boost-fs-7101

Replace self-written filesystem ops with boost.filesystem
This commit is contained in:
Michael Friedrich 2019-04-25 15:53:55 +02:00 committed by GitHub
commit 0438c866f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 65 additions and 342 deletions

View File

@ -150,13 +150,15 @@ if(LOGROTATE_HAS_SU)
set(LOGROTATE_USE_SU "\n\tsu ${ICINGA2_USER} ${ICINGA2_GROUP}")
endif()
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS context coroutine date_time thread system program_options regex REQUIRED)
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS context coroutine date_time filesystem thread system program_options regex REQUIRED)
# Boost.Coroutine2 (the successor of Boost.Coroutine)
# (1) doesn't even exist in old Boost versions and
# (2) isn't supported by ASIO, yet.
add_definitions(-DBOOST_COROUTINES_NO_DEPRECATION_WARNING)
add_definitions(-DBOOST_FILESYSTEM_NO_DEPRECATED)
link_directories(${Boost_LIBRARY_DIRS})
include_directories(${Boost_INCLUDE_DIRS})

View File

@ -505,16 +505,7 @@ void ConfigObject::DumpObjects(const String& filename, int attributeTypes)
fp.close();
#ifdef _WIN32
_unlink(filename.CStr());
#endif /* _WIN32 */
if (rename(tempFilename.CStr(), filename.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempFilename));
}
Utility::RenameFile(tempFilename, filename);
}
void ConfigObject::RestoreObject(const String& message, int attributeTypes)

View File

@ -112,15 +112,6 @@ void ScriptGlobal::WriteToFile(const String& filename)
fp.close();
#ifdef _WIN32
_unlink(filename.CStr());
#endif /* _WIN32 */
if (rename(tempFilename.CStr(), filename.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempFilename));
}
Utility::RenameFile(tempFilename, filename);
}

View File

@ -11,7 +11,10 @@
#include "base/objectlock.hpp"
#include <cstdint>
#include <mmatch.h>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/system/error_code.hpp>
#include <boost/thread/tss.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/replace.hpp>
@ -249,47 +252,7 @@ bool Utility::CidrMatch(const String& pattern, const String& ip)
*/
String Utility::DirName(const String& path)
{
char *dir;
#ifdef _WIN32
String dupPath = path;
/* PathRemoveFileSpec doesn't properly handle forward slashes. */
for (char& ch : dupPath) {
if (ch == '/')
ch = '\\';
}
dir = strdup(dupPath.CStr());
#else /* _WIN32 */
dir = strdup(path.CStr());
#endif /* _WIN32 */
if (!dir)
BOOST_THROW_EXCEPTION(std::bad_alloc());
String result;
#ifndef _WIN32
result = dirname(dir);
#else /* _WIN32 */
if (dir[0] != 0 && !PathRemoveFileSpec(dir)) {
free(dir);
BOOST_THROW_EXCEPTION(win32_error()
<< boost::errinfo_api_function("PathRemoveFileSpec")
<< errinfo_win32_error(GetLastError()));
}
result = dir;
if (result.IsEmpty())
result = ".";
#endif /* _WIN32 */
free(dir);
return result;
return boost::filesystem::path(path.Begin(), path.End()).parent_path().string();
}
/**
@ -300,21 +263,7 @@ String Utility::DirName(const String& path)
*/
String Utility::BaseName(const String& path)
{
char *dir = strdup(path.CStr());
String result;
if (!dir)
BOOST_THROW_EXCEPTION(std::bad_alloc());
#ifndef _WIN32
result = basename(dir);
#else /* _WIN32 */
result = PathFindFileName(dir);
#endif /* _WIN32 */
free(dir);
return result;
return boost::filesystem::path(path.Begin(), path.End()).filename().string();
}
/**
@ -753,38 +702,18 @@ void Utility::MkDirP(const String& path, int mode)
}
}
void Utility::RemoveDirRecursive(const String& path)
void Utility::Remove(const String& path)
{
std::vector<String> paths;
Utility::GlobRecursive(path, "*", std::bind(&Utility::CollectPaths, _1, std::ref(paths)), GlobFile | GlobDirectory);
namespace fs = boost::filesystem;
/* This relies on the fact that GlobRecursive lists the parent directory
* first before recursing into subdirectories.
*/
std::reverse(paths.begin(), paths.end());
for (const String& path : paths) {
if (remove(path.CStr()) < 0)
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("remove")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(path));
}
#ifndef _WIN32
if (rmdir(path.CStr()) < 0)
#else /* _WIN32 */
if (_rmdir(path.CStr()) < 0)
#endif /* _WIN32 */
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rmdir")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(path));
(void)fs::remove(fs::path(path.Begin(), path.End()));
}
void Utility::CollectPaths(const String& path, std::vector<String>& paths)
void Utility::RemoveDirRecursive(const String& path)
{
paths.push_back(path);
namespace fs = boost::filesystem;
(void)fs::remove_all(fs::path(path.Begin(), path.End()));
}
/*
@ -793,10 +722,20 @@ void Utility::CollectPaths(const String& path, std::vector<String>& paths)
*/
void Utility::CopyFile(const String& source, const String& target)
{
std::ifstream ifs(source.CStr(), std::ios::binary);
std::ofstream ofs(target.CStr(), std::ios::binary | std::ios::trunc);
namespace fs = boost::filesystem;
ofs << ifs.rdbuf();
fs::copy_file(fs::path(source.Begin(), source.End()), fs::path(target.Begin(), target.End()), fs::copy_option::overwrite_if_exists);
}
/*
* Renames a source file to a target location.
* Caller must ensure that the target's base directory exists and is writable.
*/
void Utility::RenameFile(const String& source, const String& target)
{
namespace fs = boost::filesystem;
fs::rename(fs::path(source.Begin(), source.End()), fs::path(target.Begin(), target.End()));
}
/*
@ -1339,13 +1278,11 @@ tm Utility::LocalTime(time_t ts)
bool Utility::PathExists(const String& path)
{
#ifndef _WIN32
struct stat statbuf;
return (lstat(path.CStr(), &statbuf) >= 0);
#else /* _WIN32 */
struct _stat statbuf;
return (_stat(path.CStr(), &statbuf) >= 0);
#endif /* _WIN32 */
namespace fs = boost::filesystem;
boost::system::error_code ec;
return fs::exists(fs::path(path.Begin(), path.End()), ec) && !ec;
}
Value Utility::LoadJsonFile(const String& path)
@ -1365,6 +1302,8 @@ Value Utility::LoadJsonFile(const String& path)
void Utility::SaveJsonFile(const String& path, int mode, const Value& value)
{
namespace fs = boost::filesystem;
std::fstream fp;
String tempFilename = Utility::CreateTempFile(path + ".XXXXXX", mode, fp);
@ -1372,16 +1311,7 @@ void Utility::SaveJsonFile(const String& path, int mode, const Value& value)
fp << JsonEncode(value);
fp.close();
#ifdef _WIN32
_unlink(path.CStr());
#endif /* _WIN32 */
if (rename(tempFilename.CStr(), path.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempFilename));
}
RenameFile(tempFilename, path);
}
static void HexEncode(char ch, std::ostream& os)

View File

@ -111,8 +111,10 @@ public:
static bool PathExists(const String& path);
static void Remove(const String& path);
static void RemoveDirRecursive(const String& path);
static void CopyFile(const String& source, const String& target);
static void RenameFile(const String& source, const String& target);
static Value LoadJsonFile(const String& path);
static void SaveJsonFile(const String& path, int mode, const Value& value);
@ -143,7 +145,6 @@ public:
private:
Utility();
static void CollectPaths(const String& path, std::vector<String>& paths);
#ifdef _WIN32
static int MksTemp (char *tmpl);

View File

@ -175,16 +175,7 @@ bool ApiSetupUtility::SetupMasterApiUser()
fp.close();
#ifdef _WIN32
_unlink(apiUsersPath.CStr());
#endif /* _WIN32 */
if (rename(tempFilename.CStr(), apiUsersPath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempFilename));
}
Utility::RenameFile(tempFilename, apiUsersPath);
return true;
}

View File

@ -207,16 +207,7 @@ int NodeSetupCommand::SetupMaster(const boost::program_options::variables_map& v
fp.close();
#ifdef _WIN32
_unlink(apipath.CStr());
#endif /* _WIN32 */
if (rename(tempApiPath.CStr(), apipath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempApiPath));
}
Utility::RenameFile(tempApiPath, apipath);
/* update constants.conf with NodeName = CN + TicketSalt = random value */
if (cn != Utility::GetFQDN()) {
@ -472,17 +463,7 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm,
fp.close();
#ifdef _WIN32
_unlink(apipath.CStr());
#endif /* _WIN32 */
if (rename(tempApiPath.CStr(), apipath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempApiPath));
}
Utility::RenameFile(tempApiPath, apipath);
/* Generate zones configuration. */
Log(LogInformation, "cli", "Generating zone and object configuration.");
@ -543,16 +524,7 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm,
fp.close();
#ifdef _WIN32
_unlink(ticketPath.CStr());
#endif /* _WIN32 */
if (rename(tempTicketPath.CStr(), ticketPath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempTicketPath));
}
Utility::RenameFile(tempTicketPath, ticketPath);
}
/* If no parent connection was made, the user must supply the ca.crt before restarting Icinga 2.*/

View File

@ -181,16 +181,7 @@ bool NodeUtility::WriteNodeConfigObjects(const String& filename, const Array::Pt
fp << std::endl;
fp.close();
#ifdef _WIN32
_unlink(filename.CStr());
#endif /* _WIN32 */
if (rename(tempFilename.CStr(), filename.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempFilename));
}
Utility::RenameFile(tempFilename, filename);
return true;
}
@ -360,16 +351,7 @@ bool NodeUtility::UpdateConfiguration(const String& value, bool include, bool re
ifp.close();
ofp.close();
#ifdef _WIN32
_unlink(configurationFile.CStr());
#endif /* _WIN32 */
if (rename(tempFile.CStr(), configurationFile.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(configurationFile));
}
Utility::RenameFile(tempFile, configurationFile);
return (found || include);
}
@ -404,14 +386,5 @@ void NodeUtility::UpdateConstant(const String& name, const String& value)
ifp.close();
ofp.close();
#ifdef _WIN32
_unlink(constantsConfPath.CStr());
#endif /* _WIN32 */
if (rename(tempFile.CStr(), constantsConfPath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(constantsConfPath));
}
Utility::RenameFile(tempFile, constantsConfPath);
}

View File

@ -470,16 +470,7 @@ wizard_ticket:
fp.close();
#ifdef _WIN32
_unlink(apiConfPath.CStr());
#endif /* _WIN32 */
if (rename(tempApiConfPath.CStr(), apiConfPath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempApiConfPath));
}
Utility::RenameFile(tempApiConfPath, apiConfPath);
/* Zones configuration. */
Log(LogInformation, "cli", "Generating local zones.conf.");
@ -578,16 +569,7 @@ wizard_global_zone_loop_start:
fp.close();
#ifdef _WIN32
_unlink(ticketPath.CStr());
#endif /* _WIN32 */
if (rename(tempTicketPath.CStr(), ticketPath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempTicketPath));
}
Utility::RenameFile(tempTicketPath, ticketPath);
}
/* If no parent connection was made, the user must supply the ca.crt before restarting Icinga 2.*/
@ -782,16 +764,7 @@ wizard_global_zone_loop_start:
fp.close();
#ifdef _WIN32
_unlink(apiConfPath.CStr());
#endif /* _WIN32 */
if (rename(tempApiConfPath.CStr(), apiConfPath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempApiConfPath));
}
Utility::RenameFile(tempApiConfPath, apiConfPath);
/* update constants.conf with NodeName = CN + TicketSalt = random value */
if (cn != Utility::GetFQDN()) {

View File

@ -107,17 +107,9 @@ void CheckResultReader::ProcessCheckResultFile(const String& path) const
}
/* Remove the checkresult files. */
if (unlink(path.CStr()) < 0)
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("unlink")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(path));
Utility::Remove(path);
if (unlink(crfile.CStr()) < 0)
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("unlink")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(crfile));
Utility::Remove(crfile);
Checkable::Ptr checkable;

View File

@ -67,12 +67,7 @@ void ExternalCommandListener::CommandPipeThread(const String& commandPath)
if (S_ISFIFO(statbuf.st_mode) && access(commandPath.CStr(), R_OK) >= 0) {
fifo_ok = true;
} else {
if (unlink(commandPath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("unlink")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(commandPath));
}
Utility::Remove(commandPath);
}
}

View File

@ -763,16 +763,7 @@ void StatusDataWriter::UpdateObjectsCache()
objectfp.close();
#ifdef _WIN32
_unlink(objectsPath.CStr());
#endif /* _WIN32 */
if (rename(tempObjectsPath.CStr(), objectsPath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempObjectsPath));
}
Utility::RenameFile(tempObjectsPath, objectsPath);
}
/**
@ -845,16 +836,7 @@ void StatusDataWriter::StatusTimerHandler()
statusfp.close();
#ifdef _WIN32
_unlink(statusPath.CStr());
#endif /* _WIN32 */
if (rename(tempStatusPath.CStr(), statusPath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempStatusPath));
}
Utility::RenameFile(tempStatusPath, statusPath);
Log(LogNotice, "StatusDataWriter")
<< "Writing status.dat file took " << Utility::FormatDuration(Utility::GetTime() - start);

View File

@ -63,15 +63,6 @@ void ConfigCompilerContext::FinishObjectsFile()
delete m_ObjectsFP;
m_ObjectsFP = nullptr;
#ifdef _WIN32
_unlink(m_ObjectsPath.CStr());
#endif /* _WIN32 */
if (rename(m_ObjectsTempFile.CStr(), m_ObjectsPath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(m_ObjectsTempFile));
}
Utility::RenameFile(m_ObjectsTempFile, m_ObjectsPath);
}

View File

@ -178,16 +178,7 @@ void IcingaApplication::DumpModifiedAttributes()
fp.close();
#ifdef _WIN32
_unlink(path.CStr());
#endif /* _WIN32 */
if (rename(tempFilename.CStr(), path.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempFilename));
}
Utility::RenameFile(tempFilename, path);
}
IcingaApplication::Ptr IcingaApplication::GetInstance()

View File

@ -155,12 +155,7 @@ void PerfdataWriter::RotateFile(std::ofstream& output, const String& temp_path,
Log(LogDebug, "PerfdataWriter")
<< "Closed output file and renaming into '" << finalFile << "'.";
if (rename(temp_path.CStr(), finalFile.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(temp_path));
}
Utility::RenameFile(temp_path, finalFile);
}
}

View File

@ -1605,12 +1605,5 @@ void ApiListener::RemoveStatusFile()
{
String path = Configuration::CacheDir + "/api-state.json";
if (Utility::PathExists(path)) {
if (unlink(path.CStr()) < 0 && errno != ENOENT) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("unlink")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(path));
}
}
Utility::Remove(path);
}

View File

@ -125,12 +125,7 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full
/* Disable logging for object creation, but do so ourselves later on. */
if (!ConfigItem::CommitItems(ascope.GetContext(), upq, newItems, true) || !ConfigItem::ActivateItems(upq, newItems, true, true)) {
if (errors) {
if (unlink(path.CStr()) < 0 && errno != ENOENT) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("unlink")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(path));
}
Utility::Remove(path);
for (const boost::exception_ptr& ex : upq.GetExceptions()) {
errors->Add(DiagnosticInformation(ex, false));
@ -155,12 +150,7 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full
<< "Created and activated object '" << fullName << "' of type '" << type->GetName() << "'.";
} catch (const std::exception& ex) {
if (unlink(path.CStr()) < 0 && errno != ENOENT) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("unlink")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(path));
}
Utility::Remove(path);
if (errors)
errors->Add(DiagnosticInformation(ex, false));
@ -227,14 +217,7 @@ bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bo
String path = GetObjectConfigPath(object->GetReflectionType(), name);
if (Utility::PathExists(path)) {
if (unlink(path.CStr()) < 0 && errno != ENOENT) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("unlink")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(path));
}
}
Utility::Remove(path);
return true;
}

View File

@ -334,16 +334,7 @@ Value UpdateCertificateHandler(const MessageOrigin::Ptr& origin, const Dictionar
cafp << ca;
cafp.close();
#ifdef _WIN32
_unlink(caPath.CStr());
#endif /* _WIN32 */
if (rename(tempCaPath.CStr(), caPath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempCaPath));
}
Utility::RenameFile(tempCaPath, caPath);
/* Update signed certificate. */
String certPath = listener->GetDefaultCertPath();
@ -356,26 +347,12 @@ Value UpdateCertificateHandler(const MessageOrigin::Ptr& origin, const Dictionar
certfp << cert;
certfp.close();
#ifdef _WIN32
_unlink(certPath.CStr());
#endif /* _WIN32 */
if (rename(tempCertPath.CStr(), certPath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempCertPath));
}
Utility::RenameFile(tempCertPath, certPath);
/* Remove ticket for successful signing request. */
String ticketPath = ApiListener::GetCertsDir() + "/ticket";
if (unlink(ticketPath.CStr()) < 0 && errno != ENOENT) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("unlink")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(ticketPath));
}
Utility::Remove(ticketPath);
/* Update the certificates at runtime and reconnect all endpoints. */
Log(LogInformation, "JsonRpcConnection")