From ea6998dcade9edf8c9d2a3f8606647ccb681c3b0 Mon Sep 17 00:00:00 2001 From: Alexander Shaduri Date: Mon, 22 Apr 2024 17:17:00 +0400 Subject: [PATCH] Support parsing ATA Directory Log in JSON. --- src/applib/smartctl_json_ata_parser.cpp | 99 ++++++++++++++++++++++--- src/applib/smartctl_text_ata_parser.cpp | 1 + 2 files changed, 89 insertions(+), 11 deletions(-) diff --git a/src/applib/smartctl_json_ata_parser.cpp b/src/applib/smartctl_json_ata_parser.cpp index ec9bd5d..829943d 100644 --- a/src/applib/smartctl_json_ata_parser.cpp +++ b/src/applib/smartctl_json_ata_parser.cpp @@ -14,6 +14,7 @@ Copyright: #include #include #include +#include #include #include #include @@ -517,15 +518,6 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_attri { using namespace SmartctlJsonParserHelpers; - std::string attrs_array_key = "ata_smart_attributes/table"; - auto attrs_node = get_node(json_root_node, attrs_array_key); - if (!attrs_node) { - return hz::Unexpected(SmartctlParserError::KeyNotFound, attrs_node.error().message()); - } - if (!attrs_node->is_array()) { - return hz::Unexpected(SmartctlParserError::DataError, std::format("Node {} is not an array.", attrs_array_key)); - } - // Revision { AtaStorageProperty p; @@ -535,8 +527,17 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_attri add_property(p); } + std::string table_key = "ata_smart_attributes/table"; + auto table_node = get_node(json_root_node, table_key); + if (!table_node) { + return hz::Unexpected(SmartctlParserError::KeyNotFound, table_node.error().message()); + } + if (!table_node->is_array()) { + return hz::Unexpected(SmartctlParserError::DataError, std::format("Node {} is not an array.", table_key)); + } + // Attributes - for (const auto& attr : attrs_node.value()) { + for (const auto& attr : table_node.value()) { AtaStorageAttribute a; a.id = get_node_data(attr, "id").value_or(0); @@ -573,7 +574,83 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_attri hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_directory_log(const nlohmann::json& json_root_node) { - return hz::ExpectedVoid(); + using namespace SmartctlJsonParserHelpers; + using namespace std::string_literals; + + std::vector lines; + + { + AtaStorageProperty p; + p.set_name("ata_log_directory/gp_dir_version", "ata_log_directory/gp_dir_version", _("General purpose log directory version")); + p.section = AtaStorageProperty::Section::DirectoryLog; + p.value = get_node_data(json_root_node, "ata_log_directory/gp_dir_version").value_or(0); + add_property(p); + + lines.emplace_back(std::format("General Purpose Log Directory Version: {}", p.get_value())); + } + { + AtaStorageProperty p; + p.set_name("ata_log_directory/smart_dir_version", "ata_log_directory/smart_dir_version", _("SMART log directory version")); + p.section = AtaStorageProperty::Section::DirectoryLog; + p.value = get_node_data(json_root_node, "ata_log_directory/smart_dir_version").value_or(0); + add_property(p); + + lines.emplace_back(std::format("SMART Log Directory Version: {}", p.get_value())); + } + { + AtaStorageProperty p; + p.set_name("ata_log_directory/smart_dir_multi_sector", "ata_log_directory/smart_dir_multi_sector", _("Multi-sector log support")); + p.section = AtaStorageProperty::Section::DirectoryLog; + p.value = get_node_data(json_root_node, "ata_log_directory/smart_dir_multi_sector").value_or(0); + add_property(p); + + lines.emplace_back(std::format("Multi-sector log support: {}", p.get_value() ? "Yes" : "No")); + } + + // Table + std::string table_key = "ata_log_directory/table"; + auto table_node = get_node(json_root_node, table_key); + if (!table_node) { + return hz::Unexpected(SmartctlParserError::KeyNotFound, table_node.error().message()); + } + if (!table_node->is_array()) { + return hz::Unexpected(SmartctlParserError::DataError, std::format("Node {} is not an array.", table_key)); + } + + // Attributes + for (const auto& table_entry : table_node.value()) { + const uint64_t address = get_node_data(table_entry, "address").value_or(0); + const std::string name = get_node_data(table_entry, "name").value_or(std::string()); + const bool read = get_node_data(table_entry, "read").value_or(false); + const bool write = get_node_data(table_entry, "write").value_or(false); + const uint64_t gp_sectors = get_node_data(table_entry, "gp_sectors").value_or(0); + const uint64_t smart_sectors = get_node_data(table_entry, "smart_sectors").value_or(0); + + // Address, GPL/SL, RO/RW, Num Sectors (GPL, Smart) , Name + // 0x00 GPL,SL R/O 1 Log Directory + lines.emplace_back(std::format( + "0x{:02X} GPL Sectors: {:8} SL Sectors: {:8} {}{} {}", + address, + gp_sectors == 0 ? "-" : std::to_string(gp_sectors), + smart_sectors == 0 ? "-" : std::to_string(smart_sectors), + (read ? "R" : "-"), + (write ? "W" : "-"), + name)); + } + + // The whole section + { + AtaStorageProperty p; + p.set_name("General Purpose Log Directory", "ata_log_directory/_merged"); + p.section = AtaStorageProperty::Section::DirectoryLog; + p.reported_value = hz::string_join(lines, "\n"); + p.value = p.reported_value; // string-type value + + add_property(p); + } + + + return {}; } diff --git a/src/applib/smartctl_text_ata_parser.cpp b/src/applib/smartctl_text_ata_parser.cpp index 5b5ef7d..0c17d96 100644 --- a/src/applib/smartctl_text_ata_parser.cpp +++ b/src/applib/smartctl_text_ata_parser.cpp @@ -13,6 +13,7 @@ Copyright: // #include "local_glibmm.h" #include // localeconv +#include #include #include #include