elog_entry: Implement getEntry method

The getEntry method returns the file descriptor to the Entry file.
This method uses its File Path property to determine the path to
the Entry file. The file descriptor is then scheduled to be closed
once the D-Bus call returns.

Tested: Verified calling this method returned a fd that was able to
read the file data from.

Change-Id: I176db463158eb755b325db5769ef4ab993c966ec
Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
diff --git a/elog_entry.cpp b/elog_entry.cpp
index 36a3fb2..9c5d213 100644
--- a/elog_entry.cpp
+++ b/elog_entry.cpp
@@ -3,6 +3,10 @@
 #include "elog_serialize.hpp"
 #include "log_manager.hpp"
 
+#include <unistd.h>
+
+#include <xyz/openbmc_project/Common/File/error.hpp>
+
 namespace phosphor
 {
 namespace logging
@@ -37,5 +41,34 @@
     return current;
 }
 
+sdbusplus::message::unix_fd Entry::getEntry()
+{
+    FILE* fp = fopen(path().c_str(), "rb");
+    if (fp == nullptr)
+    {
+        auto e = errno;
+        log<level::ERR>("Failed to open Entry File", entry("ERRNO=%d", e),
+                        entry("PATH=%s", path().c_str()));
+        throw sdbusplus::xyz::openbmc_project::Common::File::Error::Open();
+    }
+
+    auto fd = fileno(fp);
+
+    // Schedule the fd to be closed by sdbusplus when it sends it back over
+    // D-Bus.
+    sdeventplus::Event event = sdeventplus::Event::get_default();
+    fdCloseEventSource = std::make_unique<sdeventplus::source::Defer>(
+        event, std::bind(std::mem_fn(&Entry::closeFD), this, fd,
+                         std::placeholders::_1));
+
+    return fd;
+}
+
+void Entry::closeFD(int fd, sdeventplus::source::EventBase& source)
+{
+    close(fd);
+    fdCloseEventSource.reset();
+}
+
 } // namespace logging
 } // namespace phosphor
diff --git a/elog_entry.hpp b/elog_entry.hpp
index b64e1ba..0a100f4 100644
--- a/elog_entry.hpp
+++ b/elog_entry.hpp
@@ -6,6 +6,8 @@
 
 #include <sdbusplus/bus.hpp>
 #include <sdbusplus/server/object.hpp>
+#include <sdeventplus/event.hpp>
+#include <sdeventplus/source/event.hpp>
 #include <xyz/openbmc_project/Association/Definitions/server.hpp>
 #include <xyz/openbmc_project/Common/FilePath/server.hpp>
 
@@ -122,12 +124,33 @@
      */
     static constexpr auto sevLowerLimit = Entry::Level::Informational;
 
+    /**
+     * @brief Returns the file descriptor to the Entry file.
+     * @return unix_fd - File descriptor to the Entry file.
+     */
+    sdbusplus::message::unix_fd getEntry() override;
+
   private:
     /** @brief This entry's associations */
     AssociationList assocs = {};
 
     /** @brief This entry's parent */
     internal::Manager& parent;
+
+    /**
+     * @brief The event source for closing the Entry file descriptor after it
+     *        has been returned from the getEntry D-Bus method.
+     */
+    std::unique_ptr<sdeventplus::source::Defer> fdCloseEventSource;
+
+    /**
+     * @brief Closes the file descriptor passed in.
+     * @details This is called from the event loop to close FDs returned from
+     * getEntry().
+     * @param[in] fd - The file descriptor to close
+     * @param[in] source - The event source object used
+     */
+    void closeFD(int fd, sdeventplus::source::EventBase& source);
 };
 
 } // namespace logging