PEL: Create TemporaryFile class
Added support for creating temporary file
- Constructor creates the temporary file with data
- Destructor doesn't deletes file due to PEL function
related requirements.
- Provided remove function to delete the file.
Tested: Added test cases for TemporaryFile class and verified
test_openpower_pels_temporary_file OK 0.03s
Signed-off-by: Jayanth Othayoth <ojayanth@in.ibm.com>
Change-Id: I5295998d746ef1228512545f0a19faa1f94260d8
diff --git a/extensions/openpower-pels/meson.build b/extensions/openpower-pels/meson.build
index 068f870..fc8362a 100644
--- a/extensions/openpower-pels/meson.build
+++ b/extensions/openpower-pels/meson.build
@@ -30,6 +30,7 @@
endif
extra_sources = []
+
build_phal = get_option('phal').enabled()
if build_phal
@@ -64,6 +65,7 @@
'service_indicators.cpp',
'severity.cpp',
'user_header.cpp',
+ 'temporary_file.cpp',
extra_sources,
)
diff --git a/extensions/openpower-pels/temporary_file.cpp b/extensions/openpower-pels/temporary_file.cpp
new file mode 100644
index 0000000..5c52ccc
--- /dev/null
+++ b/extensions/openpower-pels/temporary_file.cpp
@@ -0,0 +1,79 @@
+#include "temporary_file.hpp"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <stdexcept>
+
+namespace openpower
+{
+namespace pels
+{
+namespace util
+{
+
+TemporaryFile::TemporaryFile(const char* data, const uint32_t len)
+{
+ // Build template path required by mkstemp()
+ std::string templatePath =
+ fs::temp_directory_path() / "phosphor-logging-XXXXXX";
+
+ // Generate unique file name, create file, and open it. The XXXXXX
+ // characters are replaced by mkstemp() to make the file name unique.
+ fd = mkostemp(templatePath.data(), O_RDWR);
+ if (fd == -1)
+ {
+ throw std::runtime_error{
+ std::string{"Unable to create temporary file: "} + strerror(errno)};
+ }
+
+ // Update file with input Buffer data
+ auto rc = write(fd, data, len);
+ if (rc == -1)
+ {
+ // 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 update file: "} +
+ strerror(errno)};
+ }
+
+ // Store path to temporary file
+ path = templatePath;
+}
+
+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 util
+} // namespace pels
+} // namespace openpower
diff --git a/extensions/openpower-pels/temporary_file.hpp b/extensions/openpower-pels/temporary_file.hpp
new file mode 100644
index 0000000..76c9e6a
--- /dev/null
+++ b/extensions/openpower-pels/temporary_file.hpp
@@ -0,0 +1,120 @@
+#pragma once
+
+#include <filesystem>
+#include <utility>
+
+namespace openpower
+{
+namespace pels
+{
+namespace util
+{
+
+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().
+ *
+ * Note: Callers responsibility to delete the file after usage.
+ * The temporary file can be deleted by calling remove().
+ *
+ * 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.
+ *
+ * @param data - data buffer
+ * @param len - length of the data buffer
+ */
+ TemporaryFile(const char* data, const uint32_t len);
+
+ /**
+ * 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.
+ */
+ ~TemporaryFile()
+ {
+ }
+
+ /**
+ * 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;
+ }
+
+ int getFd() const
+ {
+ return fd;
+ }
+
+ private:
+ /**
+ * Absolute path to the temporary file.
+ */
+ fs::path path{};
+
+ /**
+ * File descriptor of the temporary file.
+ */
+ int fd;
+};
+
+} // namespace util
+} // namespace pels
+} // namespace openpower