Track the SEL erase time

It is useful to know the last time SEL Clear was called, so
save the timestamp in a file and return it in the Get SEL Info
response.

Tested:
Ran 'ipmitool sel info' and noted the time.
Ran 'ipmitool sel clear'
Ran 'ipmitool sel info' and confirmed time had updated.

Change-Id: I81626a3bc78ffe06316a14422fab4f42a9f18217
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
diff --git a/src/storagecommands.cpp b/src/storagecommands.cpp
index 1d294f9..b8bfd56 100644
--- a/src/storagecommands.cpp
+++ b/src/storagecommands.cpp
@@ -29,6 +29,50 @@
 #include <storagecommands.hpp>
 #include <string_view>
 
+namespace intel_oem::ipmi::sel::erase_time
+{
+static constexpr const char* selEraseTimestamp = "/var/lib/ipmi/sel_erase_time";
+
+void save()
+{
+    // open the file, creating it if necessary
+    int fd = open(selEraseTimestamp, O_WRONLY | O_CREAT | O_CLOEXEC, 0644);
+    if (fd < 0)
+    {
+        std::cerr << "Failed to open file\n";
+        return;
+    }
+
+    // update the file timestamp to the current time
+    if (futimens(fd, NULL) < 0)
+    {
+        std::cerr << "Failed to update timestamp: "
+                  << std::string(strerror(errno));
+    }
+    close(fd);
+}
+
+int get()
+{
+    struct stat st;
+    // default to an invalid timestamp
+    int timestamp = ::ipmi::sel::invalidTimeStamp;
+
+    int fd = open(selEraseTimestamp, O_RDWR | O_CLOEXEC, 0644);
+    if (fd < 0)
+    {
+        return timestamp;
+    }
+
+    if (fstat(fd, &st) >= 0)
+    {
+        timestamp = st.st_mtime;
+    }
+
+    return timestamp;
+}
+} // namespace intel_oem::ipmi::sel::erase_time
+
 namespace ipmi
 {
 
@@ -519,12 +563,13 @@
         static_cast<ipmi::sel::GetSELInfoResponse*>(response);
 
     responseData->selVersion = ipmi::sel::selVersion;
-    // Last erase timestamp is not available from log manager.
-    responseData->eraseTimeStamp = ipmi::sel::invalidTimeStamp;
     responseData->addTimeStamp = ipmi::sel::invalidTimeStamp;
     responseData->operationSupport = intel_oem::ipmi::sel::selOperationSupport;
     responseData->entries = 0;
 
+    // Fill in the last erase time
+    responseData->eraseTimeStamp = intel_oem::ipmi::sel::erase_time::get();
+
     // Open the journal
     sd_journal* journalTmp = nullptr;
     if (int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY); ret < 0)
@@ -1039,6 +1084,9 @@
     // Per the IPMI spec, need to cancel any reservation when the SEL is cleared
     cancelSELReservation();
 
+    // Save the erase time
+    intel_oem::ipmi::sel::erase_time::save();
+
     // Clear the SEL by by rotating the journal to start a new file then
     // vacuuming to keep only the new file
     if (boost::process::system("/bin/journalctl", "--rotate") != 0)