blob: 76de76ccc287db0b276d2ae37c26dd08c59dbe53 [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 IIIb45eb5e2020-12-23 11:47:05 -080015 auto info = std::make_unique<BlobInfo>();
16 info->blobId = std::move(config.blobId);
17 info->actions = std::move(config.actions);
18 info->handler = std::move(config.handler);
19 if (!blobInfoMap.try_emplace(info->blobId, std::move(info)).second)
William A. Kennington IIIabf17352020-12-22 21:07:11 -080020 {
21 fprintf(stderr, "Ignoring duplicate config for %s\n",
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080022 info->blobId.c_str());
William A. Kennington IIIabf17352020-12-22 21:07:11 -080023 }
Jason Lingc78bfc82020-11-05 18:58:16 -080024 }
Jason Lingc78bfc82020-11-05 18:58:16 -080025}
26
27bool VersionBlobHandler::canHandleBlob(const std::string& path)
28{
William A. Kennington IIIabf17352020-12-22 21:07:11 -080029 return blobInfoMap.find(path) != blobInfoMap.end();
Jason Lingc78bfc82020-11-05 18:58:16 -080030}
31
32std::vector<std::string> VersionBlobHandler::getBlobIds()
33{
William A. Kennington IIIabf17352020-12-22 21:07:11 -080034 std::vector<std::string> ret;
35 for (const auto& [key, _] : blobInfoMap)
36 {
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080037 ret.emplace_back(key);
William A. Kennington IIIabf17352020-12-22 21:07:11 -080038 }
39 return ret;
Jason Lingc78bfc82020-11-05 18:58:16 -080040}
41
42/**
43 * deleteBlob - does nothing, always fails
44 */
45bool VersionBlobHandler::deleteBlob(const std::string& path)
46{
47 return false;
48}
49
50bool VersionBlobHandler::stat(const std::string& path, blobs::BlobMeta* meta)
51{
52 // TODO: stat should return the blob state and in the meta data information
53 // on whether a read is successful should be contained
54 // do things like determine if systemd target is triggered
55 // then check if file can be opened for read
56 return false; /* not yet implemented */
57}
58
59bool VersionBlobHandler::open(uint16_t session, uint16_t flags,
60 const std::string& path)
61{
Jason Lingc78bfc82020-11-05 18:58:16 -080062 /* only reads are supported, check if blob is handled and make sure
63 * the blob isn't already opened
64 */
65 if (flags != blobs::read)
66 {
67 fprintf(stderr, "open %s fail: unsupported flags(0x%04X.)\n",
68 path.c_str(), flags);
Jason Lingc78bfc82020-11-05 18:58:16 -080069 return false;
70 }
Jason Lingc78bfc82020-11-05 18:58:16 -080071
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080072 auto& v = *blobInfoMap.at(path);
73 auto [it, emplaced] = sessionToBlob.try_emplace(session, &v);
74 if (!emplaced)
Jason Lingc78bfc82020-11-05 18:58:16 -080075 {
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080076 fprintf(stderr, "open %s fail: session number %d assigned to %s\n",
77 path.c_str(), session, it->second->blobId.c_str());
78 return false;
Jason Lingc78bfc82020-11-05 18:58:16 -080079 }
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080080
81 if (v.blobState == blobs::StateFlags::open_read)
Jason Lingc78bfc82020-11-05 18:58:16 -080082 {
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080083 fprintf(stderr, "open %s fail: blob already opened for read\n",
84 path.c_str());
Jason Lingc78bfc82020-11-05 18:58:16 -080085 cleanup(session);
86 return false;
87 }
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080088 if (v.actions->onOpen->trigger() == false)
89 {
90 fprintf(stderr, "open %s fail: onOpen trigger failed\n", path.c_str());
91 cleanup(session);
92 return false;
93 }
94 v.blobState = blobs::StateFlags::open_read;
95 return true;
Jason Lingc78bfc82020-11-05 18:58:16 -080096}
97
98std::vector<uint8_t> VersionBlobHandler::read(uint16_t session, uint32_t offset,
99 uint32_t requestedSize)
100{
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800101 BlobInfo* pack;
Jason Lingc78bfc82020-11-05 18:58:16 -0800102 try
103 {
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -0800104 pack = sessionToBlob.at(session);
Jason Lingc78bfc82020-11-05 18:58:16 -0800105 }
106 catch (const std::out_of_range& e)
107 {
108 return {};
109 }
110 /* onOpen trigger must be successful, otherwise potential
111 * for stale data to be read
112 */
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800113 if (pack->actions->onOpen->status() != ActionStatus::success)
Jason Lingc78bfc82020-11-05 18:58:16 -0800114 {
115 fprintf(stderr, "read failed: onOpen trigger not successful\n");
116 return {};
117 }
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800118 if (!pack->handler->open("don't care", std::ios::in))
Jason Lingc78bfc82020-11-05 18:58:16 -0800119 {
120 fprintf(stderr, "read failed: file open unsuccessful blob=%s\n",
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -0800121 pack->blobId.c_str());
Jason Lingc78bfc82020-11-05 18:58:16 -0800122 return {};
123 }
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800124 auto d = pack->handler->read(offset, requestedSize);
Jason Lingc78bfc82020-11-05 18:58:16 -0800125 if (!d)
126 {
127 fprintf(stderr, "read failed: unable to read file for blob %s\n",
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -0800128 pack->blobId.c_str());
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800129 pack->handler->close();
Jason Lingc78bfc82020-11-05 18:58:16 -0800130 return {};
131 }
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800132 pack->handler->close();
Jason Lingc78bfc82020-11-05 18:58:16 -0800133 return *d;
134}
135
136bool VersionBlobHandler::close(uint16_t session)
137{
138 return cleanup(session);
139}
140
141bool VersionBlobHandler::stat(uint16_t session, blobs::BlobMeta* meta)
142{
143 return false;
144}
145
146bool VersionBlobHandler::expire(uint16_t session)
147{
148 return cleanup(session);
149}
150
151bool VersionBlobHandler::cleanup(uint16_t session)
152{
153 try
154 {
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -0800155 auto& pack = *sessionToBlob.at(session);
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800156 if (pack.actions->onOpen->status() == ActionStatus::running)
Jason Lingc78bfc82020-11-05 18:58:16 -0800157 {
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800158 pack.actions->onOpen->abort();
Jason Lingc78bfc82020-11-05 18:58:16 -0800159 }
160 pack.blobState = static_cast<blobs::StateFlags>(0);
161 sessionToBlob.erase(session);
162 return true;
163 }
164 catch (const std::out_of_range& e)
165 {
166 return false;
167 }
168}
169} // namespace ipmi_flash