Move TemporaryFile class to root directory

Source code that is shared across applications is located in the root
directory of the phosphor-power repository.

The TemporaryFile class was originally created for the
phosphor-regulators application.  However it is general purpose and is
now needed by the phosphor-power-sequencer application.

Move the TemporaryFile class to the root directory.  Update C++ files
that use the TemporaryFile class since it is now in a different
namespace.  Update affected meson.build files.

Change-Id: I6d18080d2436a5da87b7ab51ac003c503caa36a3
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
diff --git a/phosphor-regulators/src/ffdc_file.hpp b/phosphor-regulators/src/ffdc_file.hpp
index 923f09e..8ee9db8 100644
--- a/phosphor-regulators/src/ffdc_file.hpp
+++ b/phosphor-regulators/src/ffdc_file.hpp
@@ -29,6 +29,7 @@
 using FFDCFormat =
     sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat;
 using FileDescriptor = phosphor::power::util::FileDescriptor;
+using TemporaryFile = phosphor::power::util::TemporaryFile;
 
 /**
  * @class FFDCFile
diff --git a/phosphor-regulators/src/meson.build b/phosphor-regulators/src/meson.build
index c448366..e1552fe 100644
--- a/phosphor-regulators/src/meson.build
+++ b/phosphor-regulators/src/meson.build
@@ -24,7 +24,6 @@
     'rail.cpp',
     'sensor_monitoring.cpp',
     'system.cpp',
-    'temporary_file.cpp',
     'vpd.cpp',
 
     'actions/compare_presence_action.cpp',
diff --git a/phosphor-regulators/src/temporary_file.cpp b/phosphor-regulators/src/temporary_file.cpp
deleted file mode 100644
index 5b5954d..0000000
--- a/phosphor-regulators/src/temporary_file.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * Copyright © 2020 IBM Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "temporary_file.hpp"
-
-#include <errno.h>  // for errno
-#include <stdlib.h> // for mkstemp()
-#include <string.h> // for strerror()
-#include <unistd.h> // for close()
-
-#include <stdexcept>
-#include <string>
-
-namespace phosphor::power::regulators
-{
-
-TemporaryFile::TemporaryFile()
-{
-    // Build template path required by mkstemp()
-    std::string templatePath = fs::temp_directory_path() /
-                               "phosphor-regulators-XXXXXX";
-
-    // Generate unique file name, create file, and open it.  The XXXXXX
-    // characters are replaced by mkstemp() to make the file name unique.
-    int fd = mkstemp(templatePath.data());
-    if (fd == -1)
-    {
-        throw std::runtime_error{
-            std::string{"Unable to create temporary file: "} + strerror(errno)};
-    }
-
-    // Store path to temporary file
-    path = templatePath;
-
-    // Close file descriptor
-    if (close(fd) == -1)
-    {
-        // Save errno value; will likely change when we delete temporary file
-        int savedErrno = errno;
-
-        // Delete temporary file.  The destructor won't be called because the
-        // exception below causes this constructor to exit without completing.
-        remove();
-
-        throw std::runtime_error{
-            std::string{"Unable to close temporary file: "} +
-            strerror(savedErrno)};
-    }
-}
-
-TemporaryFile& TemporaryFile::operator=(TemporaryFile&& file)
-{
-    // Verify not assigning object to itself (a = std::move(a))
-    if (this != &file)
-    {
-        // Delete temporary file owned by this object
-        remove();
-
-        // Move temporary file path from other object, transferring ownership
-        path = std::move(file.path);
-
-        // Clear path in other object; after move path is in unspecified state
-        file.path.clear();
-    }
-    return *this;
-}
-
-void TemporaryFile::remove()
-{
-    if (!path.empty())
-    {
-        // Delete temporary file from file system
-        fs::remove(path);
-
-        // Clear path to indicate file has been deleted
-        path.clear();
-    }
-}
-
-} // namespace phosphor::power::regulators
diff --git a/phosphor-regulators/src/temporary_file.hpp b/phosphor-regulators/src/temporary_file.hpp
deleted file mode 100644
index df97ee2..0000000
--- a/phosphor-regulators/src/temporary_file.hpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/**
- * Copyright © 2020 IBM Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <filesystem>
-#include <utility>
-
-namespace phosphor::power::regulators
-{
-
-namespace fs = std::filesystem;
-
-/**
- * @class TemporaryFile
- *
- * A temporary file in the file system.
- *
- * The temporary file is created by the constructor.  The absolute path to the
- * file can be obtained using getPath().
- *
- * The temporary file can be deleted by calling remove().  Otherwise the file
- * will be deleted by the destructor.
- *
- * TemporaryFile objects cannot be copied, but they can be moved.  This enables
- * them to be stored in containers like std::vector.
- */
-class TemporaryFile
-{
-  public:
-    // Specify which compiler-generated methods we want
-    TemporaryFile(const TemporaryFile&) = delete;
-    TemporaryFile& operator=(const TemporaryFile&) = delete;
-
-    /**
-     * Constructor.
-     *
-     * Creates a temporary file in the temporary directory (normally /tmp).
-     *
-     * Throws an exception if the file cannot be created.
-     */
-    TemporaryFile();
-
-    /**
-     * Move constructor.
-     *
-     * Transfers ownership of a temporary file.
-     *
-     * @param file TemporaryFile object being moved
-     */
-    TemporaryFile(TemporaryFile&& file) : path{std::move(file.path)}
-    {
-        // Clear path in other object; after move path is in unspecified state
-        file.path.clear();
-    }
-
-    /**
-     * Move assignment operator.
-     *
-     * Deletes the temporary file owned by this object.  Then transfers
-     * ownership of the temporary file owned by the other object.
-     *
-     * Throws an exception if an error occurs during the deletion.
-     *
-     * @param file TemporaryFile object being moved
-     */
-    TemporaryFile& operator=(TemporaryFile&& file);
-
-    /**
-     * Destructor.
-     *
-     * Deletes the temporary file if necessary.
-     */
-    ~TemporaryFile()
-    {
-        try
-        {
-            remove();
-        }
-        catch (...)
-        {
-            // Destructors should not throw exceptions
-        }
-    }
-
-    /**
-     * Deletes the temporary file.
-     *
-     * Does nothing if the file has already been deleted.
-     *
-     * Throws an exception if an error occurs during the deletion.
-     */
-    void remove();
-
-    /**
-     * Returns the absolute path to the temporary file.
-     *
-     * Returns an empty path if the file has been deleted.
-     *
-     * @return temporary file path
-     */
-    const fs::path& getPath() const
-    {
-        return path;
-    }
-
-  private:
-    /**
-     * Absolute path to the temporary file.
-     *
-     * Empty when file has been deleted.
-     */
-    fs::path path{};
-};
-
-} // namespace phosphor::power::regulators
diff --git a/phosphor-regulators/test/config_file_parser_tests.cpp b/phosphor-regulators/test/config_file_parser_tests.cpp
index f477d41..92096fb 100644
--- a/phosphor-regulators/test/config_file_parser_tests.cpp
+++ b/phosphor-regulators/test/config_file_parser_tests.cpp
@@ -69,6 +69,7 @@
 using namespace phosphor::power::regulators::config_file_parser;
 using namespace phosphor::power::regulators::config_file_parser::internal;
 using json = nlohmann::json;
+using TemporaryFile = phosphor::power::util::TemporaryFile;
 
 void writeConfigFile(const std::filesystem::path& pathName,
                      const std::string& contents)
diff --git a/phosphor-regulators/test/meson.build b/phosphor-regulators/test/meson.build
index 74695be..3373abb 100644
--- a/phosphor-regulators/test/meson.build
+++ b/phosphor-regulators/test/meson.build
@@ -24,7 +24,6 @@
     'sensor_monitoring_tests.cpp',
     'sensors_tests.cpp',
     'system_tests.cpp',
-    'temporary_file_tests.cpp',
     'write_verification_error_tests.cpp',
 
     'actions/action_environment_tests.cpp',
@@ -72,7 +71,8 @@
                 build_rpath: get_option('oe-sdk').allowed() ? rpath : '',
                 link_with: [
                     phosphor_regulators_library,
-                    libi2c_dev_mock
+                    libi2c_dev_mock,
+                    libpower
                 ],
                 implicit_include_directories: false,
                 include_directories: [
diff --git a/phosphor-regulators/test/temporary_file_tests.cpp b/phosphor-regulators/test/temporary_file_tests.cpp
deleted file mode 100644
index b3bcb60..0000000
--- a/phosphor-regulators/test/temporary_file_tests.cpp
+++ /dev/null
@@ -1,277 +0,0 @@
-/**
- * Copyright © 2020 IBM Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "temporary_file.hpp"
-#include "test_utils.hpp"
-
-#include <filesystem>
-#include <string>
-#include <utility>
-
-#include <gtest/gtest.h>
-
-using namespace phosphor::power::regulators;
-using namespace phosphor::power::regulators::test_utils;
-namespace fs = std::filesystem;
-
-TEST(TemporaryFileTests, DefaultConstructor)
-{
-    TemporaryFile file{};
-
-    fs::path path = file.getPath();
-    EXPECT_FALSE(path.empty());
-    EXPECT_TRUE(fs::exists(path));
-    EXPECT_TRUE(fs::is_regular_file(path));
-
-    fs::path parentDir = path.parent_path();
-    EXPECT_EQ(parentDir, "/tmp");
-
-    std::string fileName = path.filename();
-    std::string namePrefix = "phosphor-regulators-";
-    EXPECT_EQ(fileName.compare(0, namePrefix.size(), namePrefix), 0);
-}
-
-TEST(TemporaryFileTests, MoveConstructor)
-{
-    // Create first TemporaryFile object and verify temporary file exists
-    TemporaryFile file1{};
-    EXPECT_FALSE(file1.getPath().empty());
-    EXPECT_TRUE(fs::exists(file1.getPath()));
-
-    // Save path to temporary file
-    fs::path path = file1.getPath();
-
-    // Create second TemporaryFile object by moving first object
-    TemporaryFile file2{std::move(file1)};
-
-    // Verify first object now has an empty path
-    EXPECT_TRUE(file1.getPath().empty());
-
-    // Verify second object now owns same temporary file and file exists
-    EXPECT_EQ(file2.getPath(), path);
-    EXPECT_TRUE(fs::exists(file2.getPath()));
-}
-
-TEST(TemporaryFileTests, MoveAssignmentOperator)
-{
-    // Test where works: TemporaryFile object is moved
-    {
-        // Create first TemporaryFile object and verify temporary file exists
-        TemporaryFile file1{};
-        EXPECT_FALSE(file1.getPath().empty());
-        EXPECT_TRUE(fs::exists(file1.getPath()));
-
-        // Save path to first temporary file
-        fs::path path1 = file1.getPath();
-
-        // Create second TemporaryFile object and verify temporary file exists
-        TemporaryFile file2{};
-        EXPECT_FALSE(file2.getPath().empty());
-        EXPECT_TRUE(fs::exists(file2.getPath()));
-
-        // Save path to second temporary file
-        fs::path path2 = file2.getPath();
-
-        // Verify temporary files are different
-        EXPECT_NE(path1, path2);
-
-        // Move first object into the second
-        file2 = std::move(file1);
-
-        // Verify first object now has an empty path
-        EXPECT_TRUE(file1.getPath().empty());
-
-        // Verify second object now owns first temporary file and file exists
-        EXPECT_EQ(file2.getPath(), path1);
-        EXPECT_TRUE(fs::exists(path1));
-
-        // Verify second temporary file was deleted
-        EXPECT_FALSE(fs::exists(path2));
-    }
-
-    // Test where does nothing: TemporaryFile object is moved into itself
-    {
-        // Create TemporaryFile object and verify temporary file exists
-        TemporaryFile file{};
-        EXPECT_FALSE(file.getPath().empty());
-        EXPECT_TRUE(fs::exists(file.getPath()));
-
-        // Save path to temporary file
-        fs::path path = file.getPath();
-
-        // Try to move object into itself; should do nothing
-        file = static_cast<TemporaryFile&&>(file);
-
-        // Verify object still owns same temporary file and file exists
-        EXPECT_EQ(file.getPath(), path);
-        EXPECT_TRUE(fs::exists(path));
-    }
-
-    // Test where fails: Cannot delete temporary file
-    {
-        // Create first TemporaryFile object and verify temporary file exists
-        TemporaryFile file1{};
-        EXPECT_FALSE(file1.getPath().empty());
-        EXPECT_TRUE(fs::exists(file1.getPath()));
-
-        // Save path to first temporary file
-        fs::path path1 = file1.getPath();
-
-        // Create second TemporaryFile object and verify temporary file exists
-        TemporaryFile file2{};
-        EXPECT_FALSE(file2.getPath().empty());
-        EXPECT_TRUE(fs::exists(file2.getPath()));
-
-        // Save path to second temporary file
-        fs::path path2 = file2.getPath();
-
-        // Verify temporary files are different
-        EXPECT_NE(path1, path2);
-
-        // Make second temporary file unremoveable
-        makeFileUnRemovable(path2);
-
-        try
-        {
-            // Try to move first object into the second; should throw exception
-            file2 = std::move(file1);
-            ADD_FAILURE() << "Should not have reached this line.";
-        }
-        catch (const std::exception& e)
-        {
-            // This is expected.  Exception message will vary.
-        }
-
-        // Verify first object has not changed and first temporary file exists
-        EXPECT_EQ(file1.getPath(), path1);
-        EXPECT_TRUE(fs::exists(path1));
-
-        // Verify second object has not changed and second temporary file exists
-        EXPECT_EQ(file2.getPath(), path2);
-        EXPECT_TRUE(fs::exists(path2));
-
-        // Make second temporary file removeable so destructor can delete it
-        makeFileRemovable(path2);
-    }
-}
-
-TEST(TemporaryFileTests, Destructor)
-{
-    // Test where works: Temporary file is deleted
-    {
-        fs::path path{};
-        {
-            TemporaryFile file{};
-            path = file.getPath();
-            EXPECT_TRUE(fs::exists(path));
-        }
-        EXPECT_FALSE(fs::exists(path));
-    }
-
-    // Test where works: Temporary file was already deleted
-    {
-        fs::path path{};
-        {
-            TemporaryFile file{};
-            path = file.getPath();
-            EXPECT_TRUE(fs::exists(path));
-            file.remove();
-            EXPECT_FALSE(fs::exists(path));
-        }
-        EXPECT_FALSE(fs::exists(path));
-    }
-
-    // Test where fails: Cannot delete temporary file: No exception thrown
-    {
-        fs::path path{};
-        try
-        {
-            TemporaryFile file{};
-            path = file.getPath();
-            EXPECT_TRUE(fs::exists(path));
-            makeFileUnRemovable(path);
-        }
-        catch (...)
-        {
-            ADD_FAILURE() << "Should not have caught exception.";
-        }
-
-        // Temporary file should still exist
-        EXPECT_TRUE(fs::exists(path));
-
-        // Make file removable and delete it
-        makeFileRemovable(path);
-        fs::remove(path);
-    }
-}
-
-TEST(TemporaryFileTests, Remove)
-{
-    // Test where works
-    {
-        // Create TemporaryFile object and verify temporary file exists
-        TemporaryFile file{};
-        EXPECT_FALSE(file.getPath().empty());
-        EXPECT_TRUE(fs::exists(file.getPath()));
-
-        // Save path to temporary file
-        fs::path path = file.getPath();
-
-        // Delete temporary file
-        file.remove();
-
-        // Verify path is cleared and file does not exist
-        EXPECT_TRUE(file.getPath().empty());
-        EXPECT_FALSE(fs::exists(path));
-
-        // Delete temporary file again; should do nothing
-        file.remove();
-        EXPECT_TRUE(file.getPath().empty());
-        EXPECT_FALSE(fs::exists(path));
-    }
-
-    // Test where fails
-    {
-        // Create TemporaryFile object and verify temporary file exists
-        TemporaryFile file{};
-        EXPECT_FALSE(file.getPath().empty());
-        EXPECT_TRUE(fs::exists(file.getPath()));
-
-        // Make file unremovable
-        makeFileUnRemovable(file.getPath());
-
-        try
-        {
-            // Try to delete temporary file; should fail with exception
-            file.remove();
-            ADD_FAILURE() << "Should not have reached this line.";
-        }
-        catch (const std::exception& e)
-        {
-            // This is expected.  Exception message will vary.
-        }
-
-        // Make file removable again so it will be deleted by the destructor
-        makeFileRemovable(file.getPath());
-    }
-}
-
-TEST(TemporaryFileTests, GetPath)
-{
-    TemporaryFile file{};
-    EXPECT_FALSE(file.getPath().empty());
-    EXPECT_EQ(file.getPath().parent_path(), "/tmp");
-    EXPECT_TRUE(fs::exists(file.getPath()));
-}
diff --git a/phosphor-regulators/test/validate-regulators-config_tests.cpp b/phosphor-regulators/test/validate-regulators-config_tests.cpp
index 10cd7ce..3bc52da 100644
--- a/phosphor-regulators/test/validate-regulators-config_tests.cpp
+++ b/phosphor-regulators/test/validate-regulators-config_tests.cpp
@@ -36,8 +36,8 @@
     expectJsonInvalid(configFileJson, expectedErrorMessage,                    \
                       expectedOutputMessage)
 
-using namespace phosphor::power::regulators;
 using json = nlohmann::json;
+using TemporaryFile = phosphor::power::util::TemporaryFile;
 
 const json validConfigFile = R"(
     {