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