1 #include "file_table.hpp" 2 3 #include <libpldm/utils.h> 4 5 #include <phosphor-logging/lg2.hpp> 6 7 #include <fstream> 8 9 PHOSPHOR_LOG2_USING; 10 11 namespace pldm 12 { 13 namespace filetable 14 { 15 FileTable::FileTable(const std::string& fileTableConfigPath) 16 { 17 std::ifstream jsonFile(fileTableConfigPath); 18 if (!jsonFile.is_open()) 19 { 20 error("File table config file does not exist, FILE={TABLE_CONFIG_PATH}", 21 "TABLE_CONFIG_PATH", fileTableConfigPath.c_str()); 22 return; 23 } 24 25 auto data = Json::parse(jsonFile, nullptr, false); 26 if (data.is_discarded()) 27 { 28 error("Parsing config file failed"); 29 return; 30 } 31 32 uint16_t fileNameLength = 0; 33 uint32_t fileSize = 0; 34 uint32_t traits = 0; 35 size_t tableSize = 0; 36 Handle handle = 0; 37 auto iter = fileTable.begin(); 38 39 // Iterate through each JSON object in the config file 40 for (const auto& record : data) 41 { 42 constexpr auto path = "path"; 43 constexpr auto fileTraits = "file_traits"; 44 45 std::string filepath = record.value(path, ""); 46 traits = static_cast<uint32_t>(record.value(fileTraits, 0)); 47 48 // Split the filepath string using ',' as a delimiter 49 // as the json can define multiple paths to try and use 50 // in order of priority 51 std::istringstream stringstream(filepath); 52 std::string path_substr; 53 fs::path fsPath; 54 while (std::getline(stringstream, path_substr, ',')) 55 { 56 fsPath.assign(path_substr); 57 if (fs::exists(fsPath)) 58 { 59 break; 60 } 61 } 62 63 // Skip file table entry if it is not a regular file 64 if (!fs::is_regular_file(fsPath)) 65 { 66 continue; 67 } 68 69 fileNameLength = 70 static_cast<uint16_t>(fsPath.filename().string().size()); 71 fileSize = static_cast<uint32_t>(fs::file_size(fsPath)); 72 tableSize = fileTable.size(); 73 74 fileTable.resize(tableSize + sizeof(handle) + sizeof(fileNameLength) + 75 fileNameLength + sizeof(fileSize) + sizeof(traits)); 76 iter = fileTable.begin() + tableSize; 77 78 // Populate the file table with the contents of the JSON entry 79 std::copy_n(reinterpret_cast<uint8_t*>(&handle), sizeof(handle), iter); 80 std::advance(iter, sizeof(handle)); 81 82 std::copy_n(reinterpret_cast<uint8_t*>(&fileNameLength), 83 sizeof(fileNameLength), iter); 84 std::advance(iter, sizeof(fileNameLength)); 85 86 std::copy_n(reinterpret_cast<const uint8_t*>(fsPath.filename().c_str()), 87 fileNameLength, iter); 88 std::advance(iter, fileNameLength); 89 90 std::copy_n(reinterpret_cast<uint8_t*>(&fileSize), sizeof(fileSize), 91 iter); 92 std::advance(iter, sizeof(fileSize)); 93 94 std::copy_n(reinterpret_cast<uint8_t*>(&traits), sizeof(traits), iter); 95 std::advance(iter, sizeof(traits)); 96 97 // Create the file entry for the JSON entry 98 FileEntry entry{}; 99 entry.handle = handle; 100 entry.fsPath = std::move(fsPath); 101 entry.traits.value = traits; 102 103 // Insert the file entries in the map 104 tableEntries.emplace(handle, std::move(entry)); 105 handle++; 106 } 107 108 constexpr uint8_t padWidth = 4; 109 tableSize = fileTable.size(); 110 // Add pad bytes 111 if ((tableSize % padWidth) != 0) 112 { 113 padCount = padWidth - (tableSize % padWidth); 114 fileTable.resize(tableSize + padCount, 0); 115 } 116 117 // Calculate the checksum 118 checkSum = crc32(fileTable.data(), fileTable.size()); 119 } 120 121 Table FileTable::operator()() const 122 { 123 Table table(fileTable); 124 table.resize(fileTable.size() + sizeof(checkSum)); 125 auto iter = table.begin() + fileTable.size(); 126 std::copy_n(reinterpret_cast<const uint8_t*>(&checkSum), sizeof(checkSum), 127 iter); 128 return table; 129 } 130 131 FileTable& buildFileTable(const std::string& fileTablePath) 132 { 133 static FileTable table; 134 if (table.isEmpty()) 135 { 136 table = std::move(FileTable(fileTablePath)); 137 } 138 return table; 139 } 140 141 } // namespace filetable 142 } // namespace pldm 143