blob: 6cb836881918733680ec5470c39e8fc3cfa4f879 [file] [log] [blame]
Jason Lingc78bfc82020-11-05 18:58:16 -08001#include "version_handler.hpp"
2
3#include <stdexcept>
William A. Kennington IIIabf17352020-12-22 21:07:11 -08004#include <utility>
5#include <vector>
6
Jason Lingc78bfc82020-11-05 18:58:16 -08007namespace ipmi_flash
8{
William A. Kennington IIIabf17352020-12-22 21:07:11 -08009
10VersionBlobHandler::VersionBlobHandler(
11 std::vector<HandlerConfig<ActionPack>>&& configs)
Jason Lingc78bfc82020-11-05 18:58:16 -080012{
William A. Kennington IIIabf17352020-12-22 21:07:11 -080013 for (auto& config : configs)
Jason Lingc78bfc82020-11-05 18:58:16 -080014 {
William A. Kennington IIIabf17352020-12-22 21:07:11 -080015 BlobInfo info = {std::move(config.blobId), std::move(config.actions),
16 std::move(config.handler)};
17 if (!blobInfoMap.try_emplace(info.blobId, std::move(info)).second)
18 {
19 fprintf(stderr, "Ignoring duplicate config for %s\n",
20 info.blobId.c_str());
21 }
Jason Lingc78bfc82020-11-05 18:58:16 -080022 }
Jason Lingc78bfc82020-11-05 18:58:16 -080023}
24
25bool VersionBlobHandler::canHandleBlob(const std::string& path)
26{
William A. Kennington IIIabf17352020-12-22 21:07:11 -080027 return blobInfoMap.find(path) != blobInfoMap.end();
Jason Lingc78bfc82020-11-05 18:58:16 -080028}
29
30std::vector<std::string> VersionBlobHandler::getBlobIds()
31{
William A. Kennington IIIabf17352020-12-22 21:07:11 -080032 std::vector<std::string> ret;
33 for (const auto& [key, _] : blobInfoMap)
34 {
35 ret.push_back(key);
36 }
37 return ret;
Jason Lingc78bfc82020-11-05 18:58:16 -080038}
39
40/**
41 * deleteBlob - does nothing, always fails
42 */
43bool VersionBlobHandler::deleteBlob(const std::string& path)
44{
45 return false;
46}
47
48bool VersionBlobHandler::stat(const std::string& path, blobs::BlobMeta* meta)
49{
50 // TODO: stat should return the blob state and in the meta data information
51 // on whether a read is successful should be contained
52 // do things like determine if systemd target is triggered
53 // then check if file can be opened for read
54 return false; /* not yet implemented */
55}
56
57bool VersionBlobHandler::open(uint16_t session, uint16_t flags,
58 const std::string& path)
59{
60 if (sessionToBlob.insert({session, path}).second == false)
61 {
62 fprintf(stderr, "open %s fail: session number %d assigned to %s\n",
63 path.c_str(), session, sessionToBlob.at(session).c_str());
64 return false;
65 }
66 /* only reads are supported, check if blob is handled and make sure
67 * the blob isn't already opened
68 */
69 if (flags != blobs::read)
70 {
71 fprintf(stderr, "open %s fail: unsupported flags(0x%04X.)\n",
72 path.c_str(), flags);
73 cleanup(session);
74 return false;
75 }
Jason Lingc78bfc82020-11-05 18:58:16 -080076
77 try
78 {
William A. Kennington IIIabf17352020-12-22 21:07:11 -080079 auto& v = blobInfoMap.at(path);
Jason Lingc78bfc82020-11-05 18:58:16 -080080 if (v.blobState == blobs::StateFlags::open_read)
81 {
82 cleanup(session);
83 fprintf(stderr, "open %s fail: blob already opened for read\n",
84 path.c_str());
85 return false;
86 }
William A. Kennington IIIabf17352020-12-22 21:07:11 -080087 if (v.actions->onOpen->trigger() == false)
Jason Lingc78bfc82020-11-05 18:58:16 -080088 {
89 fprintf(stderr, "open %s fail: onOpen trigger failed\n",
90 path.c_str());
91 cleanup(session);
92 return false;
93 }
94 v.blobState = blobs::StateFlags::open_read;
95 return true;
96 }
97 catch (const std::out_of_range& e)
98 {
99 fprintf(stderr, "open %s fail, exception:%s\n", path.c_str(), e.what());
100 cleanup(session);
101 return false;
102 }
103}
104
105std::vector<uint8_t> VersionBlobHandler::read(uint16_t session, uint32_t offset,
106 uint32_t requestedSize)
107{
108 std::string* blobName;
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800109 BlobInfo* pack;
Jason Lingc78bfc82020-11-05 18:58:16 -0800110 try
111 {
112 blobName = &sessionToBlob.at(session);
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800113 pack = &blobInfoMap.at(*blobName);
Jason Lingc78bfc82020-11-05 18:58:16 -0800114 }
115 catch (const std::out_of_range& e)
116 {
117 return {};
118 }
119 /* onOpen trigger must be successful, otherwise potential
120 * for stale data to be read
121 */
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800122 if (pack->actions->onOpen->status() != ActionStatus::success)
Jason Lingc78bfc82020-11-05 18:58:16 -0800123 {
124 fprintf(stderr, "read failed: onOpen trigger not successful\n");
125 return {};
126 }
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800127 if (!pack->handler->open("don't care", std::ios::in))
Jason Lingc78bfc82020-11-05 18:58:16 -0800128 {
129 fprintf(stderr, "read failed: file open unsuccessful blob=%s\n",
130 blobName->c_str());
131 return {};
132 }
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800133 auto d = pack->handler->read(offset, requestedSize);
Jason Lingc78bfc82020-11-05 18:58:16 -0800134 if (!d)
135 {
136 fprintf(stderr, "read failed: unable to read file for blob %s\n",
137 blobName->c_str());
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800138 pack->handler->close();
Jason Lingc78bfc82020-11-05 18:58:16 -0800139 return {};
140 }
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800141 pack->handler->close();
Jason Lingc78bfc82020-11-05 18:58:16 -0800142 return *d;
143}
144
145bool VersionBlobHandler::close(uint16_t session)
146{
147 return cleanup(session);
148}
149
150bool VersionBlobHandler::stat(uint16_t session, blobs::BlobMeta* meta)
151{
152 return false;
153}
154
155bool VersionBlobHandler::expire(uint16_t session)
156{
157 return cleanup(session);
158}
159
160bool VersionBlobHandler::cleanup(uint16_t session)
161{
162 try
163 {
164 const auto& blobName = sessionToBlob.at(session);
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800165 auto& pack = blobInfoMap.at(blobName);
166 if (pack.actions->onOpen->status() == ActionStatus::running)
Jason Lingc78bfc82020-11-05 18:58:16 -0800167 {
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800168 pack.actions->onOpen->abort();
Jason Lingc78bfc82020-11-05 18:58:16 -0800169 }
170 pack.blobState = static_cast<blobs::StateFlags>(0);
171 sessionToBlob.erase(session);
172 return true;
173 }
174 catch (const std::out_of_range& e)
175 {
176 return false;
177 }
178}
179} // namespace ipmi_flash