Take input from file for write keyword
This commit adds code to read keyword’s value from the local file to
update keyword’s value. User can provide file path where the value
exists using --file option.
Output:
```
Write keyword using object path (both primary and backup path VPD gets updated)
Before update:
root@p10bmc:/tmp# ./vpd-tool -O /system/chassis/motherboard -R VSYS -K BR -r
{
"/system/chassis/motherboard": {
"BR": "S0"
}
}
root@p10bmc:/tmp# ./vpd-tool -O /sys/bus/i2c/drivers/at24/8-0050/eeprom -R VSYS -K BR -r -H
{
"/sys/bus/i2c/drivers/at24/8-0050/eeprom": {
"BR": "S0"
}
}
Input file (In ASCII format):
root@p10bmc:/tmp# cat input.txt
A2
Update keyword command:
root@p10bmc:/tmp# ./vpd-tool -O /system/chassis/motherboard -R VSYS -K BR -w --file input.txt
Data updated successfully
After update:
root@p10bmc:/tmp# ./vpd-tool -O /system/chassis/motherboard -R VSYS -K BR -r
{
"/system/chassis/motherboard": {
"BR": "A2"
}
}
root@p10bmc:/tmp# ./vpd-tool -O /sys/bus/i2c/drivers/at24/8-0050/eeprom -R VSYS -K BR -r -H
{
"/sys/bus/i2c/drivers/at24/8-0050/eeprom": {
"BR": "A2"
}
}
Write keyword using hardware path (updates only given hardware path):
Input file (In hexadecimal format):
root@p10bmc:/tmp# cat input.txt
0x5330
Update keyword command:
root@p10bmc:/tmp# ./vpd-tool -O /sys/bus/i2c/drivers/at24/8-0050/eeprom -R VSYS -K BR -w -H --file input.txt
Data updated successfully
After update:
root@p10bmc:/tmp# ./vpd-tool -O /system/chassis/motherboard -R VSYS -K BR -r
{
"/system/chassis/motherboard": {
"BR": "A2"
}
}
root@p10bmc:/tmp# ./vpd-tool -O /sys/bus/i2c/drivers/at24/8-0050/eeprom -R VSYS -K BR -r -H
{
"/sys/bus/i2c/drivers/at24/8-0050/eeprom": {
"BR": "S0"
}
}
```
Change-Id: I762dceae351ab2f9a1989b664a424cda4470dd1d
Signed-off-by: Anupama B R <anupama.b.r1@ibm.com>
diff --git a/vpd-tool/include/tool_utils.hpp b/vpd-tool/include/tool_utils.hpp
index e4b0a33..4306da5 100644
--- a/vpd-tool/include/tool_utils.hpp
+++ b/vpd-tool/include/tool_utils.hpp
@@ -767,5 +767,72 @@
}
};
+/**
+ * @brief API to read value from file.
+ *
+ * The API reads the file and returns the read value.
+ *
+ * @param[in] i_filePath - File path.
+ *
+ * @return - Data from file if any in string format, else empty string.
+ *
+ */
+inline std::string readValueFromFile(const std::string& i_filePath)
+{
+ std::string l_valueRead{};
+
+ std::error_code l_ec;
+ if (!std::filesystem::exists(i_filePath, l_ec))
+ {
+ std::string l_message{
+ "filesystem call exists failed for file [" + i_filePath + "]."};
+
+ if (l_ec)
+ {
+ l_message += " Error: " + l_ec.message();
+ }
+
+ std::cerr << l_message << std::endl;
+ return l_valueRead;
+ }
+
+ if (std::filesystem::is_empty(i_filePath, l_ec))
+ {
+ std::cerr << "File[" << i_filePath << "] is empty." << std::endl;
+ return l_valueRead;
+ }
+ else if (l_ec)
+ {
+ std::cerr << "is_empty file system call failed for file[" << i_filePath
+ << "] , error: " << l_ec.message() << std::endl;
+
+ return l_valueRead;
+ }
+
+ std::ifstream l_fileStream;
+ l_fileStream.exceptions(std::ifstream::badbit | std::ifstream::failbit);
+ try
+ {
+ l_fileStream.open(i_filePath, std::ifstream::in);
+
+ std::getline(l_fileStream, l_valueRead);
+
+ l_fileStream.close();
+ return l_valueRead;
+ }
+ catch (const std::ifstream::failure& l_ex)
+ {
+ if (l_fileStream.is_open())
+ {
+ l_fileStream.close();
+ }
+
+ std::cerr << "File read operation failed for path[" << i_filePath
+ << "], error: " << l_ex.what() << std::endl;
+ }
+
+ return l_valueRead;
+}
+
} // namespace utils
} // namespace vpd
diff --git a/vpd-tool/src/vpd_tool_main.cpp b/vpd-tool/src/vpd_tool_main.cpp
index 93fdd38..c7a846f 100644
--- a/vpd-tool/src/vpd_tool_main.cpp
+++ b/vpd-tool/src/vpd_tool_main.cpp
@@ -1,4 +1,5 @@
#include "tool_constants.hpp"
+#include "tool_utils.hpp"
#include "vpd_tool.hpp"
#include <CLI/CLI.hpp>
@@ -145,13 +146,16 @@
* @param[in] i_recordName - Record name.
* @param[in] i_keywordOption - Option to pass keyword name.
* @param[in] i_keywordName - Keyword name.
+ * @param[in] i_fileOption - Option to pass file path.
+ * @param[in] i_filePath - File path.
*
* @return Success if corresponding value is found against option, failure
* otherwise.
*/
int checkOptionValuePair(const auto& i_objectOption, const auto& i_vpdPath,
const auto& i_recordOption, const auto& i_recordName,
- const auto& i_keywordOption, const auto& i_keywordName)
+ const auto& i_keywordOption, const auto& i_keywordName,
+ const auto& i_fileOption, const auto& i_filePath)
{
if (!i_objectOption->empty() && i_vpdPath.empty())
{
@@ -175,6 +179,12 @@
return vpd::constants::FAILURE;
}
+ if (!i_fileOption->empty() && i_filePath.empty())
+ {
+ std::cout << "File path is empty." << std::endl;
+ return vpd::constants::FAILURE;
+ }
+
return vpd::constants::SUCCESS;
}
@@ -242,9 +252,8 @@
auto l_keywordOption =
l_app.add_option("--keyword, -K", l_keywordName, "Keyword name");
- // Enable when file option is implemented.
- /*auto l_fileOption = l_app.add_option("--file", l_filePath,
- "Absolute file path");*/
+ auto l_fileOption =
+ l_app.add_option("--file", l_filePath, "Absolute file path");
auto l_keywordValueOption =
l_app.add_option("--value, -V", l_keywordValue,
@@ -299,7 +308,8 @@
CLI11_PARSE(l_app, argc, argv);
if (checkOptionValuePair(l_objectOption, l_vpdPath, l_recordOption,
- l_recordName, l_keywordOption, l_keywordName) ==
+ l_recordName, l_keywordOption, l_keywordName,
+ l_fileOption, l_filePath) ==
vpd::constants::FAILURE)
{
return vpd::constants::FAILURE;
@@ -313,6 +323,28 @@
if (!l_writeFlag->empty())
{
+ if ((l_keywordValueOption->empty() && l_fileOption->empty()) ||
+ (!l_keywordValueOption->empty() && !l_fileOption->empty()))
+ {
+ std::cerr
+ << "Please provide keyword value.\nUse --value/--file to give "
+ "keyword value. Refer --help."
+ << std::endl;
+ return vpd::constants::FAILURE;
+ }
+
+ if (!l_fileOption->empty())
+ {
+ l_keywordValue = vpd::utils::readValueFromFile(l_filePath);
+ if (l_keywordValue.empty())
+ {
+ return vpd::constants::FAILURE;
+ }
+
+ return writeKeyword(l_hardwareFlag, l_fileOption, l_vpdPath,
+ l_recordName, l_keywordName, l_keywordValue);
+ }
+
return writeKeyword(l_hardwareFlag, l_keywordValueOption, l_vpdPath,
l_recordName, l_keywordName, l_keywordValue);
}