]> granicus.if.org Git - icinga2/commitdiff
Fix unique creation of temp files
authorMichael Friedrich <michael.friedrich@netways.de>
Mon, 22 Feb 2016 15:47:41 +0000 (16:47 +0100)
committerMichael Friedrich <michael.friedrich@netways.de>
Tue, 23 Feb 2016 11:34:38 +0000 (12:34 +0100)
fixes #10948

14 files changed:
lib/base/configobject.cpp
lib/base/scriptglobal.cpp
lib/base/utility.cpp
lib/base/utility.hpp
lib/cli/apisetuputility.cpp
lib/cli/nodesetupcommand.cpp
lib/cli/nodeutility.cpp
lib/cli/nodewizardcommand.cpp
lib/cli/repositoryutility.cpp
lib/compat/statusdatawriter.cpp
lib/config/configcompilercontext.cpp
lib/config/configcompilercontext.hpp
lib/icinga/clusterevents.cpp
lib/icinga/icingaapplication.cpp

index 20426a603ec7b879cb4f04d88fe7ab0e1d5352c7..214b78c2f74a502898f958ea63b908c704b35fac 100644 (file)
@@ -482,10 +482,8 @@ void ConfigObject::DumpObjects(const String& filename, int attributeTypes)
        Log(LogInformation, "ConfigObject")
            << "Dumping program state to file '" << filename << "'";
 
-       String tempFilename = filename + ".tmp";
-
        std::fstream fp;
-       fp.open(tempFilename.CStr(), std::ios_base::out);
+       String tempFilename = Utility::CreateTempFile(filename + ".XXXXXX", fp);
 
        if (!fp)
                BOOST_THROW_EXCEPTION(std::runtime_error("Could not open '" + tempFilename + "' file"));
index 237e66cd1630242ca8012c2d42bfded3ee5dc622..a80484cb6a7ba614fb683a263264946b1ea1305e 100644 (file)
@@ -65,10 +65,8 @@ void ScriptGlobal::WriteToFile(const String& filename)
        Log(LogInformation, "ScriptGlobal")
                << "Dumping variables to file '" << filename << "'";
 
-       String tempFilename = filename + ".tmp";
-
        std::fstream fp;
-       fp.open(tempFilename.CStr(), std::ios_base::out);
+       String tempFilename = Utility::CreateTempFile(filename + ".XXXXXX", fp);
 
        if (!fp)
                BOOST_THROW_EXCEPTION(std::runtime_error("Could not open '" + tempFilename + "' file"));
index e02d72db2b0af99a4437718ec24b587ddcd7edb3..4a11b9c31b9fe8427e64276153dcfa4f9a3c529d 100644 (file)
@@ -53,6 +53,8 @@
 
 #ifdef _WIN32
 #      include <VersionHelpers.h>
+#      include <windows.h>
+#      include <io.h>
 #endif /*_WIN32*/
 
 using namespace icinga;
@@ -1327,9 +1329,9 @@ Value Utility::LoadJsonFile(const String& path)
 
 void Utility::SaveJsonFile(const String& path, const Value& value)
 {
-       String tempPath = path + ".tmp";
+       std::fstream fp;
+       String tempFilename = Utility::CreateTempFile(path + ".XXXXXX", fp);
 
-       std::ofstream fp(tempPath.CStr(), std::ofstream::out | std::ostream::trunc);
        fp.exceptions(std::ofstream::failbit | std::ofstream::badbit);
        fp << JsonEncode(value);
        fp.close();
@@ -1338,11 +1340,11 @@ void Utility::SaveJsonFile(const String& path, const Value& value)
        _unlink(path.CStr());
 #endif /* _WIN32 */
 
-       if (rename(tempPath.CStr(), path.CStr()) < 0) {
+       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(tempPath));
+                   << boost::errinfo_file_name(tempFilename));
        }
 }
 
@@ -1703,3 +1705,139 @@ String Utility::ValidateUTF8(const String& input)
 
        return output;
 }
+
+String Utility::CreateTempFile(const String& path, std::fstream& fp)
+{
+       std::vector<char> targetPath(path.Begin(), path.End());
+       targetPath.push_back('\0');
+
+       int fd;
+#ifndef _WIN32
+       fd = mkstemp(&targetPath[0]);
+#else /* _WIN32 */
+       fd = MksTemp(&targetPath[0]);
+#endif /*_WIN32*/
+
+       if (fd < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << boost::errinfo_api_function("mkstemp")
+                   << boost::errinfo_errno(errno)
+                   << boost::errinfo_file_name(path));
+       }
+
+       try {
+               fp.open(&targetPath[0], std::ios_base::trunc | std::ios_base::out);
+       } catch (const std::fstream::failure& e) {
+               close(fd);
+               throw;
+       }
+
+       close(fd);
+
+       return String(targetPath.begin(), targetPath.end() - 1);
+}
+
+#ifdef _WIN32
+/* mkstemp extracted from libc/sysdeps/posix/tempname.c.  Copyright
+   (C) 1991-1999, 2000, 2001, 2006 Free Software Foundation, Inc.
+
+   The GNU C Library 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 2.1 of the License, or (at your option) any later version.  */
+
+#define _O_EXCL 0x0400
+#define _O_CREAT 0x0100
+#define _O_RDWR 0x0002
+#define O_EXCL _O_EXCL
+#define O_CREAT        _O_CREAT
+#define O_RDWR _O_RDWR
+
+static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+/* Generate a temporary file name based on TMPL.  TMPL must match the
+   rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
+   does not exist at the time of the call to mkstemp.  TMPL is
+   overwritten with the result.  */
+int Utility::MksTemp(char *tmpl)
+{
+       int len;
+       char *XXXXXX;
+       static unsigned long long value;
+       unsigned long long random_time_bits;
+       unsigned int count;
+       int fd = -1;
+       int save_errno = errno;
+
+       /* A lower bound on the number of temporary files to attempt to
+       generate.  The maximum total number of temporary file names that
+       can exist for a given template is 62**6.  It should never be
+       necessary to try all these combinations.  Instead if a reasonable
+       number of names is tried (we define reasonable as 62**3) fail to
+       give the system administrator the chance to remove the problems.  */
+#define ATTEMPTS_MIN (62 * 62 * 62)
+
+       /* The number of times to attempt to generate a temporary file.  To
+          conform to POSIX, this must be no smaller than TMP_MAX.  */
+#if ATTEMPTS_MIN < TMP_MAX
+       unsigned int attempts = TMP_MAX;
+#else
+       unsigned int attempts = ATTEMPTS_MIN;
+#endif
+
+       len = strlen (tmpl);
+       if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       /* This is where the Xs start.  */
+       XXXXXX = &tmpl[len - 6];
+
+       /* Get some more or less random data.  */
+       {
+               SYSTEMTIME stNow;
+               FILETIME ftNow;
+
+               // get system time
+               GetSystemTime(&stNow);
+               stNow.wMilliseconds = 500;
+               if (!SystemTimeToFileTime(&stNow, &ftNow)) {
+                   errno = -1;
+                   return -1;
+               }
+
+               random_time_bits = (((unsigned long long)ftNow.dwHighDateTime << 32) | (unsigned long long)ftNow.dwLowDateTime);
+       }
+
+       value += random_time_bits ^ (unsigned long long)GetCurrentThreadId();
+
+       for (count = 0; count < attempts; value += 7777, ++count) {
+               unsigned long long v = value;
+
+               /* Fill in the random bits.  */
+               XXXXXX[0] = letters[v % 62];
+               v /= 62;
+               XXXXXX[1] = letters[v % 62];
+               v /= 62;
+               XXXXXX[2] = letters[v % 62];
+               v /= 62;
+               XXXXXX[3] = letters[v % 62];
+               v /= 62;
+               XXXXXX[4] = letters[v % 62];
+               v /= 62;
+               XXXXXX[5] = letters[v % 62];
+
+               fd = open(tmpl, O_RDWR | O_CREAT | O_EXCL, _S_IREAD | _S_IWRITE);
+               if (fd >= 0) {
+                       errno = save_errno;
+                       return fd;
+               } else if (errno != EEXIST)
+                       return -1;
+       }
+
+       /* We got out of the loop because we ran out of combinations to try.  */
+       errno = EEXIST;
+       return -1;
+}
+#endif /*_WIN32*/
index b986e6820cef3142d98ac4e48c6b6e3631755da6..b27ac761273142d32febe23732d8150cf2c922eb 100644 (file)
@@ -141,10 +141,16 @@ public:
 
        static String ValidateUTF8(const String& input);
 
+       static String CreateTempFile(const String& path, std::fstream& fp);
+
 private:
        Utility(void);
        static void CollectPaths(const String& path, std::vector<String>& paths);
 
+#ifdef _WIN32
+       static int MksTemp (char *tmpl);
+#endif /* _WIN32 */
+
        static boost::thread_specific_ptr<String> m_ThreadName;
        static boost::thread_specific_ptr<unsigned int> m_RandSeed;
 };
index 55ef0aa504dc923293823dba9830a1741761e698..abe7c38d6995585f16404ef5af4e904e379316fb 100644 (file)
@@ -157,23 +157,21 @@ bool ApiSetupUtility::SetupMasterApiUser(void)
 {
        String api_username = "root"; // TODO make this available as cli parameter?
        String api_password = RandomString(8);
-       String apiuserspath = GetConfdPath() + "/api-users.conf";
+       String apiUsersPath = GetConfdPath() + "/api-users.conf";
 
-       if (Utility::PathExists(apiuserspath)) {
+       if (Utility::PathExists(apiUsersPath)) {
                Log(LogInformation, "cli")
-                   << "API user config file '" << apiuserspath << "' already exists, not creating config file.";
+                   << "API user config file '" << apiUsersPath << "' already exists, not creating config file.";
                return true;
        }
 
        Log(LogInformation, "cli")
-           << "Adding new ApiUser '" << api_username << "' in '" << apiuserspath << "'.";
+           << "Adding new ApiUser '" << api_username << "' in '" << apiUsersPath << "'.";
 
-       NodeUtility::CreateBackupFile(apiuserspath);
+       NodeUtility::CreateBackupFile(apiUsersPath);
 
-       String apiuserspathtmp = apiuserspath + ".tmp";
-
-       std::ofstream fp;
-       fp.open(apiuserspathtmp.CStr(), std::ofstream::out | std::ofstream::trunc);
+       std::fstream fp;
+       String tempFilename = Utility::CreateTempFile(apiUsersPath + ".XXXXXX", fp);
 
        fp << "/**\n"
            << " * The APIUser objects are used for authentication against the API.\n"
@@ -188,14 +186,14 @@ bool ApiSetupUtility::SetupMasterApiUser(void)
        fp.close();
 
 #ifdef _WIN32
-       _unlink(apiuserspath.CStr());
+       _unlink(apiUsersPath.CStr());
 #endif /* _WIN32 */
 
-       if (rename(apiuserspathtmp.CStr(), apiuserspath.CStr()) < 0) {
+       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(apiuserspathtmp));
+                   << boost::errinfo_file_name(tempFilename));
        }
 
        return true;
index 2428f557a64c751ff71cda23e49fba28031f929a..a86d02293fa039786403de702bf9c36472d4e34a 100644 (file)
@@ -169,10 +169,8 @@ int NodeSetupCommand::SetupMaster(const boost::program_options::variables_map& v
        String apipath = FeatureUtility::GetFeaturesAvailablePath() + "/api.conf";
        NodeUtility::CreateBackupFile(apipath);
 
-       String apipathtmp = apipath + ".tmp";
-
-       std::ofstream fp;
-       fp.open(apipathtmp.CStr(), std::ofstream::out | std::ofstream::trunc);
+       std::fstream fp;
+       String tempApiPath = Utility::CreateTempFile(apipath + ".XXXXXX", fp);
 
        fp << "/**\n"
            << " * The API listener is used for distributed monitoring setups.\n"
@@ -202,11 +200,11 @@ int NodeSetupCommand::SetupMaster(const boost::program_options::variables_map& v
        _unlink(apipath.CStr());
 #endif /* _WIN32 */
 
-       if (rename(apipathtmp.CStr(), apipath.CStr()) < 0) {
+       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(apipathtmp));
+                   << boost::errinfo_file_name(tempApiPath));
        }
 
        /* update constants.conf with NodeName = CN + TicketSalt = random value */
@@ -376,10 +374,8 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm,
        String apipath = FeatureUtility::GetFeaturesAvailablePath() + "/api.conf";
        NodeUtility::CreateBackupFile(apipath);
 
-       String apipathtmp = apipath + ".tmp";
-
-       std::ofstream fp;
-       fp.open(apipathtmp.CStr(), std::ofstream::out | std::ofstream::trunc);
+       std::fstream fp;
+       String tempApiPath = Utility::CreateTempFile(apipath + ".XXXXXX", fp);
 
        fp << "/**\n"
            << " * The API listener is used for distributed monitoring setups.\n"
@@ -421,11 +417,11 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm,
        _unlink(apipath.CStr());
 #endif /* _WIN32 */
 
-       if (rename(apipathtmp.CStr(), apipath.CStr()) < 0) {
+       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(apipathtmp));
+                   << boost::errinfo_file_name(tempApiPath));
        }
 
        /* generate local zones.conf with zone+endpoint */
index a7a2e43b89f8ac5887f066da600c335037574202..3d46c66ba4b679a9a1342542f8185088f8a14bc9 100644 (file)
@@ -385,9 +385,8 @@ bool NodeUtility::WriteNodeConfigObjects(const String& filename, const Array::Pt
                    << "Cannot set ownership for user '" << user << "' group '" << group << "' on path '" << path << "'. Verify it yourself!";
        }
 
-       String tempPath = filename + ".tmp";
-
-       std::ofstream fp(tempPath.CStr(), std::ofstream::out | std::ostream::trunc);
+       std::fstream fp;
+       String tempFilename = Utility::CreateTempFile(filename + ".XXXXXX", fp);
 
        fp << "/*\n";
        fp << " * Generated by Icinga 2 node setup commands\n";
@@ -406,11 +405,11 @@ bool NodeUtility::WriteNodeConfigObjects(const String& filename, const Array::Pt
        _unlink(filename.CStr());
 #endif /* _WIN32 */
 
-       if (rename(tempPath.CStr(), filename.CStr()) < 0) {
+       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(tempPath));
+                   << boost::errinfo_file_name(tempFilename));
        }
 
        return true;
@@ -638,10 +637,10 @@ void NodeUtility::SerializeObject(std::ostream& fp, const Dictionary::Ptr& objec
 void NodeUtility::UpdateConstant(const String& name, const String& value)
 {
        String constantsFile = Application::GetSysconfDir() + "/icinga2/constants.conf";
-       String tempFile = constantsFile + ".tmp";
 
        std::ifstream ifp(constantsFile.CStr());
-       std::ofstream ofp(tempFile.CStr());
+       std::fstream ofp;
+       String tempFile = Utility::CreateTempFile(constantsFile + ".XXXXXX", ofp);
 
        bool found = false;
 
index 1d71749ef46e61ff4c44b42e9a11b34b14bbca53..079bb5a135a4caeafd5e17476cf65aac26dc343f 100644 (file)
@@ -412,10 +412,8 @@ wizard_ticket:
                String apipath = FeatureUtility::GetFeaturesAvailablePath() + "/api.conf";
                NodeUtility::CreateBackupFile(apipath);
 
-               String apipathtmp = apipath + ".tmp";
-
-               std::ofstream fp;
-               fp.open(apipathtmp.CStr(), std::ofstream::out | std::ofstream::trunc);
+               std::fstream fp;
+               String tempApiPath = Utility::CreateTempFile(apipath + ".XXXXXX", fp);
 
                fp << "/**\n"
                    << " * The API listener is used for distributed monitoring setups.\n"
@@ -443,11 +441,11 @@ wizard_ticket:
                _unlink(apipath.CStr());
 #endif /* _WIN32 */
 
-               if (rename(apipathtmp.CStr(), apipath.CStr()) < 0) {
+               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(apipathtmp));
+                           << boost::errinfo_file_name(tempApiPath));
                }
 
                /* apilistener config */
@@ -538,10 +536,9 @@ wizard_ticket:
                String apipath = FeatureUtility::GetFeaturesAvailablePath() + "/api.conf";
                NodeUtility::CreateBackupFile(apipath);
 
-               String apipathtmp = apipath + ".tmp";
 
-               std::ofstream fp;
-               fp.open(apipathtmp.CStr(), std::ofstream::out | std::ofstream::trunc);
+               std::fstream fp;
+               String tempApiPath = Utility::CreateTempFile(apipath + ".XXXXXX", fp);
 
                fp << "/**\n"
                    << " * The API listener is used for distributed monitoring setups.\n"
@@ -566,11 +563,11 @@ wizard_ticket:
                _unlink(apipath.CStr());
 #endif /* _WIN32 */
 
-               if (rename(apipathtmp.CStr(), apipath.CStr()) < 0) {
+               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(apipathtmp));
+                           << boost::errinfo_file_name(tempApiPath));
                }
 
                /* update constants.conf with NodeName = CN + TicketSalt = random value */
index e8c49a05dfe5b583b783f4d187fd961277d8f86d..157c371fbc3f929faa56f0ceaa8c9fa9f1387264 100644 (file)
@@ -356,9 +356,9 @@ bool RepositoryUtility::WriteObjectToRepositoryChangeLog(const String& path, con
 
        CreateRepositoryPath(Utility::DirName(path));
 
-       String tempPath = path + ".tmp";
+       std::fstream fp;
+       String tempFilename = Utility::CreateTempFile(path + ".XXXXXX", fp);
 
-       std::ofstream fp(tempPath.CStr(), std::ofstream::out | std::ostream::trunc);
        fp << JsonEncode(item);
        fp.close();
 
@@ -366,11 +366,11 @@ bool RepositoryUtility::WriteObjectToRepositoryChangeLog(const String& path, con
        _unlink(path.CStr());
 #endif /* _WIN32 */
 
-       if (rename(tempPath.CStr(), path.CStr()) < 0) {
+       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(tempPath));
+                   << boost::errinfo_file_name(tempFilename));
        }
 
        return true;
@@ -496,9 +496,9 @@ bool RepositoryUtility::WriteObjectToRepository(const String& path, const String
 
        CreateRepositoryPath(Utility::DirName(path));
 
-       String tempPath = path + ".tmp";
+       std::fstream fp;
+       String tempFilename = Utility::CreateTempFile(path + ".XXXXXX", fp);
 
-       std::ofstream fp(tempPath.CStr(), std::ofstream::out | std::ostream::trunc);
        SerializeObject(fp, name, type, item);
        fp << std::endl;
        fp.close();
@@ -507,11 +507,11 @@ bool RepositoryUtility::WriteObjectToRepository(const String& path, const String
        _unlink(path.CStr());
 #endif /* _WIN32 */
 
-       if (rename(tempPath.CStr(), path.CStr()) < 0) {
+       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(tempPath));
+                   << boost::errinfo_file_name(tempFilename));
        }
 
        return true;
index 818db2761cfcfeee8049e5a3802e675f67d3611e..bfd90bb476c38f0b6119c6ecb9bd1af11630d8d0 100644 (file)
@@ -536,11 +536,10 @@ void StatusDataWriter::UpdateObjectsCache(void)
 {
        CONTEXT("Writing objects.cache file");
 
-       String objectspath = GetObjectsPath();
-       String objectspathtmp = objectspath + ".tmp";
+       String objectsPath = GetObjectsPath();
 
-       std::ofstream objectfp;
-       objectfp.open(objectspathtmp.CStr(), std::ofstream::out | std::ofstream::trunc);
+       std::fstream objectfp;
+       String tempObjectsPath = Utility::CreateTempFile(objectsPath + ".XXXXXX", objectfp);
 
        objectfp << std::fixed;
 
@@ -760,14 +759,14 @@ void StatusDataWriter::UpdateObjectsCache(void)
        objectfp.close();
 
 #ifdef _WIN32
-       _unlink(objectspath.CStr());
+       _unlink(objectsPath.CStr());
 #endif /* _WIN32 */
 
-       if (rename(objectspathtmp.CStr(), objectspath.CStr()) < 0) {
+       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(objectspathtmp));
+                   << boost::errinfo_file_name(tempObjectsPath));
        }
 }
 
@@ -783,11 +782,10 @@ void StatusDataWriter::StatusTimerHandler(void)
 
        double start = Utility::GetTime();
 
-       String statuspath = GetStatusPath();
-       String statuspathtmp = statuspath + ".tmp"; /* XXX make this a global definition */
+       String statusPath = GetStatusPath();
 
-       std::ofstream statusfp;
-       statusfp.open(statuspathtmp.CStr(), std::ofstream::out | std::ofstream::trunc);
+       std::fstream statusfp;
+       String tempStatusPath = Utility::CreateTempFile(statusPath + ".XXXXXX", statusfp);
 
        statusfp << std::fixed;
 
@@ -843,14 +841,14 @@ void StatusDataWriter::StatusTimerHandler(void)
        statusfp.close();
 
 #ifdef _WIN32
-       _unlink(statuspath.CStr());
+       _unlink(statusPath.CStr());
 #endif /* _WIN32 */
 
-       if (rename(statuspathtmp.CStr(), statuspath.CStr()) < 0) {
+       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(statuspathtmp));
+                   << boost::errinfo_file_name(tempStatusPath));
        }
 
        Log(LogNotice, "StatusDataWriter")
index e4dcddd12bfb1324727508ef7518bbded64da9a6..917ee9e9f281ec33e72721ac8660e08c8050fdfa 100644 (file)
@@ -36,13 +36,11 @@ void ConfigCompilerContext::OpenObjectsFile(const String& filename)
 {
        m_ObjectsPath = filename;
 
-       String tempFilename = m_ObjectsPath + ".tmp";
-
        std::fstream *fp = new std::fstream();
-       fp->open(tempFilename.CStr(), std::ios_base::out);
+       m_ObjectsTempFile = Utility::CreateTempFile(filename + ".XXXXXX", *fp);
 
        if (!*fp)
-               BOOST_THROW_EXCEPTION(std::runtime_error("Could not open '" + tempFilename + "' file"));
+               BOOST_THROW_EXCEPTION(std::runtime_error("Could not open '" + m_ObjectsTempFile + "' file"));
 
        m_ObjectsFP = new StdioStream(fp, true);
 }
@@ -65,17 +63,15 @@ void ConfigCompilerContext::FinishObjectsFile(void)
        m_ObjectsFP->Close();
        m_ObjectsFP.reset();
 
-       String tempFilename = m_ObjectsPath + ".tmp";
-
 #ifdef _WIN32
        _unlink(m_ObjectsPath.CStr());
 #endif /* _WIN32 */
 
-       if (rename(tempFilename.CStr(), m_ObjectsPath.CStr()) < 0) {
+       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(tempFilename));
+                   << boost::errinfo_file_name(m_ObjectsTempFile));
        }
 }
 
index d0601f762b0335736f1f2cd5850d648d28a6da16..cd4f2b006e7f6bc2905945bb754c3990cf780552 100644 (file)
@@ -42,6 +42,7 @@ public:
 
 private:
        String m_ObjectsPath;
+       String m_ObjectsTempFile;
        StdioStream::Ptr m_ObjectsFP;
 
        mutable boost::mutex m_Mutex;
index 7c4e021c2d7f2e8f1a8e13b40cb4804b817c5aee..4e712cf82364bf5cca97c0a625cd3408f7902cb9 100644 (file)
@@ -722,9 +722,10 @@ Value ClusterEvents::UpdateRepositoryAPIHandler(const MessageOrigin::Ptr& origin
                return Empty;
 
        String repositoryFile = GetRepositoryDir() + SHA256(params->Get("endpoint")) + ".repo";
-       String repositoryTempFile = repositoryFile + ".tmp";
 
-       std::ofstream fp(repositoryTempFile.CStr(), std::ofstream::out | std::ostream::trunc);
+       std::fstream fp;
+       String tempRepositoryFile = Utility::CreateTempFile(repositoryFile + ".XXXXXX", fp);
+
        fp << JsonEncode(params);
        fp.close();
 
@@ -732,11 +733,11 @@ Value ClusterEvents::UpdateRepositoryAPIHandler(const MessageOrigin::Ptr& origin
        _unlink(repositoryFile.CStr());
 #endif /* _WIN32 */
 
-       if (rename(repositoryTempFile.CStr(), repositoryFile.CStr()) < 0) {
+       if (rename(tempRepositoryFile.CStr(), repositoryFile.CStr()) < 0) {
                BOOST_THROW_EXCEPTION(posix_error()
                    << boost::errinfo_api_function("rename")
                    << boost::errinfo_errno(errno)
-                   << boost::errinfo_file_name(repositoryTempFile));
+                   << boost::errinfo_file_name(tempRepositoryFile));
        }
 
        ApiListener::Ptr listener = ApiListener::GetInstance();
index 1a5ea429e42d248095d1162e75f010818c85642d..2825030d1656108238dcb19235f6d11f98fef934 100644 (file)
@@ -133,7 +133,7 @@ void IcingaApplication::OnShutdown(void)
        DumpProgramState();
 }
 
-static void PersistModAttrHelper(std::ofstream& fp, ConfigObject::Ptr& previousObject, const ConfigObject::Ptr& object, const String& attr, const Value& value)
+static void PersistModAttrHelper(std::fstream& fp, ConfigObject::Ptr& previousObject, const ConfigObject::Ptr& object, const String& attr, const Value& value)
 {
        if (object != previousObject) {
                if (previousObject) {
@@ -173,10 +173,9 @@ void IcingaApplication::DumpProgramState(void)
 void IcingaApplication::DumpModifiedAttributes(void)
 {
        String path = GetModAttrPath();
-       String pathtmp = path + ".tmp";
 
-       std::ofstream fp;
-       fp.open(pathtmp.CStr(), std::ofstream::out | std::ofstream::trunc);
+       std::fstream fp;
+       String tempFilename = Utility::CreateTempFile(path + ".XXXXXX", fp);
 
        ConfigObject::Ptr previousObject;
        ConfigObject::DumpModifiedAttributes(boost::bind(&PersistModAttrHelper, boost::ref(fp), boost::ref(previousObject), _1, _2, _3));
@@ -193,11 +192,11 @@ void IcingaApplication::DumpModifiedAttributes(void)
        _unlink(path.CStr());
 #endif /* _WIN32 */
 
-       if (rename(pathtmp.CStr(), path.CStr()) < 0) {
+       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(pathtmp));
+                   << boost::errinfo_file_name(tempFilename));
        }
 }