blob: 45d9b02d60037a188387de789c96ba3d7855c612 [file] [log] [blame]
Jason Lingc78bfc82020-11-05 18:58:16 -08001#include "version_handler.hpp"
2
William A. Kennington IIIabf17352020-12-22 21:07:11 -08003#include <utility>
4#include <vector>
5
Jason Lingc78bfc82020-11-05 18:58:16 -08006namespace ipmi_flash
7{
William A. Kennington IIIabf17352020-12-22 21:07:11 -08008
9VersionBlobHandler::VersionBlobHandler(
10 std::vector<HandlerConfig<ActionPack>>&& configs)
Jason Lingc78bfc82020-11-05 18:58:16 -080011{
William A. Kennington IIIabf17352020-12-22 21:07:11 -080012 for (auto& config : configs)
Jason Lingc78bfc82020-11-05 18:58:16 -080013 {
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080014 auto info = std::make_unique<BlobInfo>();
15 info->blobId = std::move(config.blobId);
16 info->actions = std::move(config.actions);
17 info->handler = std::move(config.handler);
William A. Kennington III9936c452020-12-23 23:31:23 -080018 info->actions->onOpen->setCallback(
19 [infoP = info.get()](TriggerableActionInterface& tai) {
20 auto data =
21 std::make_shared<std::optional<std::vector<uint8_t>>>();
22 do
23 {
24 if (tai.status() != ActionStatus::success)
25 {
26 fprintf(stderr, "Version file unit failed for %s\n",
27 infoP->blobId.c_str());
28 continue;
29 }
30 if (!infoP->handler->open("", std::ios::in))
31 {
32 fprintf(stderr, "Opening version file failed for %s\n",
33 infoP->blobId.c_str());
34 continue;
35 }
36 auto d = infoP->handler->read(
37 0, std::numeric_limits<uint32_t>::max());
38 infoP->handler->close();
39 if (!d)
40 {
41 fprintf(stderr, "Reading version file failed for %s\n",
42 infoP->blobId.c_str());
43 continue;
44 }
45 *data = std::move(d);
46 } while (false);
47 for (auto sessionP : infoP->sessionsToUpdate)
48 {
49 sessionP->data = data;
50 }
51 infoP->sessionsToUpdate.clear();
52 });
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080053 if (!blobInfoMap.try_emplace(info->blobId, std::move(info)).second)
William A. Kennington IIIabf17352020-12-22 21:07:11 -080054 {
55 fprintf(stderr, "Ignoring duplicate config for %s\n",
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080056 info->blobId.c_str());
William A. Kennington IIIabf17352020-12-22 21:07:11 -080057 }
Jason Lingc78bfc82020-11-05 18:58:16 -080058 }
Jason Lingc78bfc82020-11-05 18:58:16 -080059}
60
61bool VersionBlobHandler::canHandleBlob(const std::string& path)
62{
William A. Kennington IIIabf17352020-12-22 21:07:11 -080063 return blobInfoMap.find(path) != blobInfoMap.end();
Jason Lingc78bfc82020-11-05 18:58:16 -080064}
65
66std::vector<std::string> VersionBlobHandler::getBlobIds()
67{
William A. Kennington IIIabf17352020-12-22 21:07:11 -080068 std::vector<std::string> ret;
69 for (const auto& [key, _] : blobInfoMap)
70 {
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080071 ret.emplace_back(key);
William A. Kennington IIIabf17352020-12-22 21:07:11 -080072 }
73 return ret;
Jason Lingc78bfc82020-11-05 18:58:16 -080074}
75
76/**
77 * deleteBlob - does nothing, always fails
78 */
79bool VersionBlobHandler::deleteBlob(const std::string& path)
80{
81 return false;
82}
83
84bool VersionBlobHandler::stat(const std::string& path, blobs::BlobMeta* meta)
85{
86 // TODO: stat should return the blob state and in the meta data information
87 // on whether a read is successful should be contained
88 // do things like determine if systemd target is triggered
89 // then check if file can be opened for read
90 return false; /* not yet implemented */
91}
92
93bool VersionBlobHandler::open(uint16_t session, uint16_t flags,
94 const std::string& path)
95{
Jason Lingc78bfc82020-11-05 18:58:16 -080096 /* only reads are supported, check if blob is handled and make sure
97 * the blob isn't already opened
98 */
99 if (flags != blobs::read)
100 {
101 fprintf(stderr, "open %s fail: unsupported flags(0x%04X.)\n",
102 path.c_str(), flags);
Jason Lingc78bfc82020-11-05 18:58:16 -0800103 return false;
104 }
Jason Lingc78bfc82020-11-05 18:58:16 -0800105
William A. Kennington III9936c452020-12-23 23:31:23 -0800106 auto info = std::make_unique<SessionInfo>();
107 info->blob = blobInfoMap.at(path).get();
108 info->blob->sessionsToUpdate.emplace(info.get());
109 if (info->blob->sessionsToUpdate.size() == 1 &&
110 !info->blob->actions->onOpen->trigger())
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -0800111 {
112 fprintf(stderr, "open %s fail: onOpen trigger failed\n", path.c_str());
William A. Kennington III9936c452020-12-23 23:31:23 -0800113 info->blob->sessionsToUpdate.erase(info.get());
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -0800114 return false;
115 }
William A. Kennington III007c0162020-12-23 16:36:22 -0800116
William A. Kennington III9936c452020-12-23 23:31:23 -0800117 sessionInfoMap[session] = std::move(info);
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -0800118 return true;
Jason Lingc78bfc82020-11-05 18:58:16 -0800119}
120
121std::vector<uint8_t> VersionBlobHandler::read(uint16_t session, uint32_t offset,
122 uint32_t requestedSize)
123{
William A. Kennington III9936c452020-12-23 23:31:23 -0800124 auto& data = sessionInfoMap.at(session)->data;
125 if (data == nullptr || !*data || (*data)->size() < offset)
Jason Lingc78bfc82020-11-05 18:58:16 -0800126 {
Jason Lingc78bfc82020-11-05 18:58:16 -0800127 return {};
128 }
William A. Kennington III9936c452020-12-23 23:31:23 -0800129 std::vector<uint8_t> ret(
130 std::min<size_t>(requestedSize, (*data)->size() - offset));
131 std::memcpy(&ret[0], &(**data)[offset], ret.size());
132 return ret;
Jason Lingc78bfc82020-11-05 18:58:16 -0800133}
134
135bool VersionBlobHandler::close(uint16_t session)
136{
William A. Kennington III9936c452020-12-23 23:31:23 -0800137 auto it = sessionInfoMap.find(session);
138 if (it == sessionInfoMap.end())
Jason Lingc78bfc82020-11-05 18:58:16 -0800139 {
140 return false;
141 }
William A. Kennington III9936c452020-12-23 23:31:23 -0800142 auto& info = *it->second;
143 info.blob->sessionsToUpdate.erase(&info);
144 if (info.blob->sessionsToUpdate.empty())
145 {
146 info.blob->actions->onOpen->abort();
147 }
148 sessionInfoMap.erase(it);
149 return true;
Jason Lingc78bfc82020-11-05 18:58:16 -0800150}
William A. Kennington IIIc5b901d2020-12-23 17:07:20 -0800151
152bool VersionBlobHandler::stat(uint16_t session, blobs::BlobMeta* meta)
153{
154 return false;
155}
156
157bool VersionBlobHandler::expire(uint16_t session)
158{
159 close(session);
160 return true;
161}
162
Jason Lingc78bfc82020-11-05 18:58:16 -0800163} // namespace ipmi_flash