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