1 #include "file_table.hpp"
2 
3 #include "libpldm/utils.h"
4 
5 #include <fstream>
6 #include <iostream>
7 
8 namespace pldm
9 {
10 
11 namespace filetable
12 {
13 
14 FileTable::FileTable(const std::string& fileTableConfigPath)
15 {
16     std::ifstream jsonFile(fileTableConfigPath);
17     if (!jsonFile.is_open())
18     {
19         std::cerr << "File table config file does not exist, FILE="
20                   << fileTableConfigPath.c_str() << "\n";
21         return;
22     }
23 
24     auto data = Json::parse(jsonFile, nullptr, false);
25     if (data.is_discarded())
26     {
27         std::cerr << "Parsing config file failed"
28                   << "\n";
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     checkSum = crc32(fileTable.data(), fileTable.size());
104 }
105 
106 Table FileTable::operator()() const
107 {
108     Table table(fileTable);
109     table.resize(fileTable.size() + sizeof(checkSum));
110     auto iter = table.begin() + fileTable.size();
111     std::copy_n(reinterpret_cast<const uint8_t*>(&checkSum), sizeof(checkSum),
112                 iter);
113     return table;
114 }
115 
116 FileTable& buildFileTable(const std::string& fileTablePath)
117 {
118     static FileTable table;
119     if (table.isEmpty())
120     {
121         table = std::move(FileTable(fileTablePath));
122     }
123     return table;
124 }
125 
126 } // namespace filetable
127 } // namespace pldm
128