regulators: Create FFDCFile class

Create C++ class for a file that contains FFDC (first failure data
capture) data.

This class is used to store FFDC data in an error log.  The FFDC data is
passed to the error logging system using a file descriptor.

The constructor creates the file and opens it for both reading and
writing.  The getFileDescriptor() method returns the file descriptor for
reading/writing the file.  The destructor closes and deletes the file.

Also moved the test utility functions makeFileUnRemovable() and
makeFileRemovable() to test_utils.hpp so they can be used by multiple
testcases.

Change-Id: Iddef488a28e83a0df7e7f6955c3217ecb3ec2d51
diff --git a/phosphor-regulators/test/test_utils.hpp b/phosphor-regulators/test/test_utils.hpp
index 313d9f7..f56dc18 100644
--- a/phosphor-regulators/test/test_utils.hpp
+++ b/phosphor-regulators/test/test_utils.hpp
@@ -23,6 +23,8 @@
 #include "rail.hpp"
 #include "rule.hpp"
 
+#include <filesystem>
+#include <fstream>
 #include <memory>
 #include <string>
 #include <utility>
@@ -31,6 +33,8 @@
 namespace phosphor::power::regulators::test_utils
 {
 
+namespace fs = std::filesystem;
+
 /**
  * Create an I2CInterface object with hard-coded bus and address values.
  *
@@ -89,4 +93,43 @@
     return std::make_unique<Rule>(id, std::move(actions));
 }
 
+/**
+ * Modify the specified file so that fs::remove() fails with an exception.
+ *
+ * The file will be renamed and can be restored by calling makeFileRemovable().
+ *
+ * @param path path to the file
+ */
+inline void makeFileUnRemovable(const fs::path& path)
+{
+    // Rename the file to save its contents
+    fs::path savePath{path.native() + ".save"};
+    fs::rename(path, savePath);
+
+    // Create a directory at the original file path
+    fs::create_directory(path);
+
+    // Create a file within the directory.  fs::remove() will throw an exception
+    // if the path is a non-empty directory.
+    std::ofstream childFile{path / "childFile"};
+}
+
+/**
+ * Modify the specified file so that fs::remove() can successfully delete it.
+ *
+ * Undo the modifications from an earlier call to makeFileUnRemovable().
+ *
+ * @param path path to the file
+ */
+inline void makeFileRemovable(const fs::path& path)
+{
+    // makeFileUnRemovable() creates a directory at the file path.  Remove the
+    // directory and all of its contents.
+    fs::remove_all(path);
+
+    // Rename the file back to the original path to restore its contents
+    fs::path savePath{path.native() + ".save"};
+    fs::rename(savePath, path);
+}
+
 } // namespace phosphor::power::regulators::test_utils