blob: 48388ee2ebc817ac732d0da2abb09326bd0fb626 [file] [log] [blame]
Tom Joseph0c6d22c2019-06-26 09:58:41 +05301#include "file_table.hpp"
2
George Liu6492f522020-06-16 10:34:05 +08003#include "libpldm/utils.h"
4
Tom Joseph0c6d22c2019-06-26 09:58:41 +05305#include <fstream>
Sampa Misraaa8ae722019-12-12 03:20:40 -06006#include <iostream>
Tom Joseph0c6d22c2019-06-26 09:58:41 +05307
8namespace pldm
9{
10
11namespace filetable
12{
13
Tom Joseph0c6d22c2019-06-26 09:58:41 +053014FileTable::FileTable(const std::string& fileTableConfigPath)
15{
16 std::ifstream jsonFile(fileTableConfigPath);
17 if (!jsonFile.is_open())
18 {
Sampa Misraaa8ae722019-12-12 03:20:40 -060019 std::cerr << "File table config file does not exist, FILE="
20 << fileTableConfigPath.c_str() << "\n";
Tom Joseph0c6d22c2019-06-26 09:58:41 +053021 return;
22 }
23
24 auto data = Json::parse(jsonFile, nullptr, false);
25 if (data.is_discarded())
26 {
Sampa Misraaa8ae722019-12-12 03:20:40 -060027 std::cerr << "Parsing config file failed"
28 << "\n";
Tom Joseph0c6d22c2019-06-26 09:58:41 +053029 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
Christian Geddes3249a902021-05-08 16:27:57 -050048 // 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
Tom Joseph0c6d22c2019-06-26 09:58:41 +053064 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
George Liu077fea22020-04-08 16:47:14 +0800118 checkSum = crc32(fileTable.data(), fileTable.size());
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530119}
120
121Table 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
131FileTable& 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