blob: 8bf76bd53e2438f9b56add52d9ff067dc7f7a964 [file] [log] [blame]
Jason Lingc78bfc82020-11-05 18:58:16 -08001#include "version_handler.hpp"
2
3#include <stdexcept>
4namespace ipmi_flash
5{
6std::unique_ptr<blobs::GenericBlobInterface>
7 VersionBlobHandler::create(VersionInfoMap&& versionMap)
8{
Jason Lingc78bfc82020-11-05 18:58:16 -08009 std::vector<std::string> blobList;
10 for (const auto& [key, val] : versionMap)
11 {
Jason Lingc78bfc82020-11-05 18:58:16 -080012 blobList.push_back(key);
13 }
14 return std::make_unique<VersionBlobHandler>(std::move(blobList),
15 std::move(versionMap));
16}
17
18bool VersionBlobHandler::canHandleBlob(const std::string& path)
19{
20 return (std::find(blobIds.begin(), blobIds.end(), path) != blobIds.end());
21}
22
23std::vector<std::string> VersionBlobHandler::getBlobIds()
24{
25 return blobIds;
26}
27
28/**
29 * deleteBlob - does nothing, always fails
30 */
31bool VersionBlobHandler::deleteBlob(const std::string& path)
32{
33 return false;
34}
35
36bool VersionBlobHandler::stat(const std::string& path, blobs::BlobMeta* meta)
37{
38 // TODO: stat should return the blob state and in the meta data information
39 // on whether a read is successful should be contained
40 // do things like determine if systemd target is triggered
41 // then check if file can be opened for read
42 return false; /* not yet implemented */
43}
44
45bool VersionBlobHandler::open(uint16_t session, uint16_t flags,
46 const std::string& path)
47{
48 if (sessionToBlob.insert({session, path}).second == false)
49 {
50 fprintf(stderr, "open %s fail: session number %d assigned to %s\n",
51 path.c_str(), session, sessionToBlob.at(session).c_str());
52 return false;
53 }
54 /* only reads are supported, check if blob is handled and make sure
55 * the blob isn't already opened
56 */
57 if (flags != blobs::read)
58 {
59 fprintf(stderr, "open %s fail: unsupported flags(0x%04X.)\n",
60 path.c_str(), flags);
61 cleanup(session);
62 return false;
63 }
Jason Lingc78bfc82020-11-05 18:58:16 -080064
65 try
66 {
67 auto& v = versionInfoMap.at(path);
68 if (v.blobState == blobs::StateFlags::open_read)
69 {
70 cleanup(session);
71 fprintf(stderr, "open %s fail: blob already opened for read\n",
72 path.c_str());
73 return false;
74 }
75 if (v.actionPack->onOpen->trigger() == false)
76 {
77 fprintf(stderr, "open %s fail: onOpen trigger failed\n",
78 path.c_str());
79 cleanup(session);
80 return false;
81 }
82 v.blobState = blobs::StateFlags::open_read;
83 return true;
84 }
85 catch (const std::out_of_range& e)
86 {
87 fprintf(stderr, "open %s fail, exception:%s\n", path.c_str(), e.what());
88 cleanup(session);
89 return false;
90 }
91}
92
93std::vector<uint8_t> VersionBlobHandler::read(uint16_t session, uint32_t offset,
94 uint32_t requestedSize)
95{
96 std::string* blobName;
97 VersionInfoPack* pack;
98 try
99 {
100 blobName = &sessionToBlob.at(session);
101 pack = &versionInfoMap.at(*blobName);
102 }
103 catch (const std::out_of_range& e)
104 {
105 return {};
106 }
107 /* onOpen trigger must be successful, otherwise potential
108 * for stale data to be read
109 */
110 if (pack->actionPack->onOpen->status() != ActionStatus::success)
111 {
112 fprintf(stderr, "read failed: onOpen trigger not successful\n");
113 return {};
114 }
115 if (!pack->imageHandler->open("don't care", std::ios::in))
116 {
117 fprintf(stderr, "read failed: file open unsuccessful blob=%s\n",
118 blobName->c_str());
119 return {};
120 }
121 auto d = pack->imageHandler->read(offset, requestedSize);
122 if (!d)
123 {
124 fprintf(stderr, "read failed: unable to read file for blob %s\n",
125 blobName->c_str());
126 pack->imageHandler->close();
127 return {};
128 }
129 pack->imageHandler->close();
130 return *d;
131}
132
133bool VersionBlobHandler::close(uint16_t session)
134{
135 return cleanup(session);
136}
137
138bool VersionBlobHandler::stat(uint16_t session, blobs::BlobMeta* meta)
139{
140 return false;
141}
142
143bool VersionBlobHandler::expire(uint16_t session)
144{
145 return cleanup(session);
146}
147
148bool VersionBlobHandler::cleanup(uint16_t session)
149{
150 try
151 {
152 const auto& blobName = sessionToBlob.at(session);
153 auto& pack = versionInfoMap.at(blobName);
154 if (pack.actionPack->onOpen->status() == ActionStatus::running)
155 {
156 pack.actionPack->onOpen->abort();
157 }
158 pack.blobState = static_cast<blobs::StateFlags>(0);
159 sessionToBlob.erase(session);
160 return true;
161 }
162 catch (const std::out_of_range& e)
163 {
164 return false;
165 }
166}
167} // namespace ipmi_flash