1 #include "file_table.hpp" 2 3 #include <boost/crc.hpp> 4 #include <fstream> 5 #include <phosphor-logging/log.hpp> 6 7 namespace pldm 8 { 9 10 namespace filetable 11 { 12 13 using namespace phosphor::logging; 14 15 FileTable::FileTable(const std::string& fileTableConfigPath) 16 { 17 std::ifstream jsonFile(fileTableConfigPath); 18 if (!jsonFile.is_open()) 19 { 20 log<level::ERR>("File table config file does not exist", 21 entry("FILE=%s", fileTableConfigPath.c_str())); 22 return; 23 } 24 25 auto data = Json::parse(jsonFile, nullptr, false); 26 if (data.is_discarded()) 27 { 28 log<level::ERR>("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 fs::path fsPath(filepath); 49 if (!fs::is_regular_file(fsPath)) 50 { 51 continue; 52 } 53 54 fileNameLength = 55 static_cast<uint16_t>(fsPath.filename().string().size()); 56 fileSize = static_cast<uint32_t>(fs::file_size(fsPath)); 57 tableSize = fileTable.size(); 58 59 fileTable.resize(tableSize + sizeof(handle) + sizeof(fileNameLength) + 60 fileNameLength + sizeof(fileSize) + sizeof(traits)); 61 iter = fileTable.begin() + tableSize; 62 63 // Populate the file table with the contents of the JSON entry 64 std::copy_n(reinterpret_cast<uint8_t*>(&handle), sizeof(handle), iter); 65 std::advance(iter, sizeof(handle)); 66 67 std::copy_n(reinterpret_cast<uint8_t*>(&fileNameLength), 68 sizeof(fileNameLength), iter); 69 std::advance(iter, sizeof(fileNameLength)); 70 71 std::copy_n(reinterpret_cast<const uint8_t*>(fsPath.filename().c_str()), 72 fileNameLength, iter); 73 std::advance(iter, fileNameLength); 74 75 std::copy_n(reinterpret_cast<uint8_t*>(&fileSize), sizeof(fileSize), 76 iter); 77 std::advance(iter, sizeof(fileSize)); 78 79 std::copy_n(reinterpret_cast<uint8_t*>(&traits), sizeof(traits), iter); 80 std::advance(iter, sizeof(traits)); 81 82 // Create the file entry for the JSON entry 83 FileEntry entry{}; 84 entry.handle = handle; 85 entry.fsPath = std::move(fsPath); 86 entry.traits.value = traits; 87 88 // Insert the file entries in the map 89 tableEntries.emplace(handle, std::move(entry)); 90 handle++; 91 } 92 93 constexpr uint8_t padWidth = 4; 94 tableSize = fileTable.size(); 95 // Add pad bytes 96 if ((tableSize % padWidth) != 0) 97 { 98 padCount = padWidth - (tableSize % padWidth); 99 fileTable.resize(tableSize + padCount, 0); 100 } 101 102 // Calculate the checksum 103 boost::crc_32_type result; 104 result.process_bytes(fileTable.data(), fileTable.size()); 105 checkSum = result.checksum(); 106 } 107 108 Table FileTable::operator()() const 109 { 110 Table table(fileTable); 111 table.resize(fileTable.size() + sizeof(checkSum)); 112 auto iter = table.begin() + fileTable.size(); 113 std::copy_n(reinterpret_cast<const uint8_t*>(&checkSum), sizeof(checkSum), 114 iter); 115 return table; 116 } 117 118 FileTable& buildFileTable(const std::string& fileTablePath) 119 { 120 static FileTable table; 121 if (table.isEmpty()) 122 { 123 table = std::move(FileTable(fileTablePath)); 124 } 125 return table; 126 } 127 128 } // namespace filetable 129 } // namespace pldm 130