Fix IPMI firmware update programming failure
The IPMI Firmware Update sequence fails on some systems. The update
process receives the new firmware image data in the /tmp file
system. During the final update phase the image is copied into the
/tmp/images subdirectory. If /tmp and /tmp/images are not part of the
same filesystem the std::filesystem::rename() function fails.
This commit changes the update process. The rename() is still
attempted. In the event the rename() fails, a copy() operation is
performed in the belief the destination is on a separate filesystem.
Tested:
Confirmed this change works on systems with a common /tmp filesystem.
Confirmed this change works on systems with the source file and the
destination file on different filesystems.
Change-Id: I5e3da6c0f453941ea54cb829d2bcaeadda0db438
Signed-off-by: Johnathan Mantey <johnathanx.mantey@intel.com>
diff --git a/src/firmware-update.cpp b/src/firmware-update.cpp
index 82364d3..f8672fd 100644
--- a/src/firmware-update.cpp
+++ b/src/firmware-update.cpp
@@ -650,9 +650,26 @@
// check if it is ready for activation)
static std::unique_ptr<sdbusplus::bus::match_t> fwUpdateMatchSignal;
postTransferCompleteHandler(fwUpdateMatchSignal);
- std::filesystem::rename(
- uri, "/tmp/images/" +
- boost::uuids::to_string(boost::uuids::random_generator()()));
+ std::string randomFname =
+ "/tmp/images/" +
+ boost::uuids::to_string(boost::uuids::random_generator()());
+ std::error_code fsError{};
+ std::filesystem::rename(uri, randomFname, fsError);
+ if (fsError)
+ {
+ // The source and destination may not be in the same
+ // filesystem.
+ std::filesystem::copy(uri, randomFname, fsError);
+ if (fsError)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Unable to move/copy image to destination directory.",
+ phosphor::logging::entry("ERROR=%s",
+ fsError.message().c_str()));
+ return false;
+ }
+ std::filesystem::remove(uri);
+ }
return true;
}