functions: Delete symlink if the target doesn't match

If the symlink does not point to the expected target, delete it so that
it gets recreated to the correct target. This can happen when the BMC is
put on a different system or the system is converted to a different one
without performing a firmware update.

Tested: Manually changed a symlink and verified that it got restored to
the expected target.

Change-Id: Ia9fd49554030bad8d727304e2ff2122107c90476
Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
diff --git a/functions.cpp b/functions.cpp
index 9b1d664..0d2b34c 100644
--- a/functions.cpp
+++ b/functions.cpp
@@ -37,6 +37,8 @@
 using ManagedObjectType =
     std::map<sdbusplus::message::object_path, InterfacesPropertiesMap>;
 
+constexpr auto tocName = "pnor.toc";
+
 /**
  * @brief Returns the managed objects for a given service
  */
@@ -197,7 +199,6 @@
     auto tocLidPath = hostFirmwareDirectory / tocLid;
     if (std::filesystem::exists(tocLidPath))
     {
-        static const auto tocName = "pnor.toc";
         auto tocLinkPath = hostFirmwareDirectory / tocName;
         makeCallback(linkCallback, tocLid, tocLinkPath, errorCallback);
     }
@@ -346,14 +347,32 @@
         // "element1=lid1,element2=lid2,elementN=lidN,"
         biosAttrStr += a.first + "=" + a.second + ",";
 
-        // Create symlinks from the hostfw elements to their corresponding
-        // lid files if they don't exist
+        std::error_code ec;
+        auto lidName = a.second + ".lid";
         auto elementFilePath =
             std::filesystem::path("/media/hostfw/running") / a.first;
+
+        // Remove the symlink if the target does not match so that it gets
+        // recreated. Ignore pnor.toc, this symlink is manually created by the
+        // function findLinks().
+        if ((a.first != tocName) &&
+            std::filesystem::is_symlink(elementFilePath, ec))
+        {
+            auto target = std::filesystem::read_symlink(elementFilePath, ec);
+            if (target != lidName)
+            {
+                log<level::INFO>("Removing mismatched symlilnk",
+                                 entry("LINK=%s", elementFilePath.c_str()),
+                                 entry("TARGET=%s", target.c_str()),
+                                 entry("EXPECTED:%s", lidName.c_str()));
+                std::filesystem::remove(elementFilePath, ec);
+            }
+        }
+
+        // Create symlinks from the hostfw elements to their corresponding
+        // lid files if they don't exist
         if (!std::filesystem::exists(elementFilePath))
         {
-            std::error_code ec;
-            auto lidName = a.second + ".lid";
             std::filesystem::create_symlink(lidName, elementFilePath, ec);
             if (ec)
             {