blob: 5d667133c212683d3fd7b8667fb00523e75639eb [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);
William A. Kennington IIIfbf4c532020-12-23 11:49:03 -080073 sessionToBlob[session] = &v;
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080074
75 if (v.blobState == blobs::StateFlags::open_read)
Jason Lingc78bfc82020-11-05 18:58:16 -080076 {
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080077 fprintf(stderr, "open %s fail: blob already opened for read\n",
78 path.c_str());
Jason Lingc78bfc82020-11-05 18:58:16 -080079 cleanup(session);
80 return false;
81 }
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080082 if (v.actions->onOpen->trigger() == false)
83 {
84 fprintf(stderr, "open %s fail: onOpen trigger failed\n", path.c_str());
85 cleanup(session);
86 return false;
87 }
88 v.blobState = blobs::StateFlags::open_read;
89 return true;
Jason Lingc78bfc82020-11-05 18:58:16 -080090}
91
92std::vector<uint8_t> VersionBlobHandler::read(uint16_t session, uint32_t offset,
93 uint32_t requestedSize)
94{
William A. Kennington IIIabf17352020-12-22 21:07:11 -080095 BlobInfo* pack;
Jason Lingc78bfc82020-11-05 18:58:16 -080096 try
97 {
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080098 pack = sessionToBlob.at(session);
Jason Lingc78bfc82020-11-05 18:58:16 -080099 }
100 catch (const std::out_of_range& e)
101 {
102 return {};
103 }
104 /* onOpen trigger must be successful, otherwise potential
105 * for stale data to be read
106 */
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800107 if (pack->actions->onOpen->status() != ActionStatus::success)
Jason Lingc78bfc82020-11-05 18:58:16 -0800108 {
109 fprintf(stderr, "read failed: onOpen trigger not successful\n");
110 return {};
111 }
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800112 if (!pack->handler->open("don't care", std::ios::in))
Jason Lingc78bfc82020-11-05 18:58:16 -0800113 {
114 fprintf(stderr, "read failed: file open unsuccessful blob=%s\n",
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -0800115 pack->blobId.c_str());
Jason Lingc78bfc82020-11-05 18:58:16 -0800116 return {};
117 }
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800118 auto d = pack->handler->read(offset, requestedSize);
Jason Lingc78bfc82020-11-05 18:58:16 -0800119 if (!d)
120 {
121 fprintf(stderr, "read failed: unable to read file for blob %s\n",
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -0800122 pack->blobId.c_str());
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800123 pack->handler->close();
Jason Lingc78bfc82020-11-05 18:58:16 -0800124 return {};
125 }
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800126 pack->handler->close();
Jason Lingc78bfc82020-11-05 18:58:16 -0800127 return *d;
128}
129
130bool VersionBlobHandler::close(uint16_t session)
131{
132 return cleanup(session);
133}
134
135bool VersionBlobHandler::stat(uint16_t session, blobs::BlobMeta* meta)
136{
137 return false;
138}
139
140bool VersionBlobHandler::expire(uint16_t session)
141{
142 return cleanup(session);
143}
144
145bool VersionBlobHandler::cleanup(uint16_t session)
146{
147 try
148 {
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -0800149 auto& pack = *sessionToBlob.at(session);
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800150 if (pack.actions->onOpen->status() == ActionStatus::running)
Jason Lingc78bfc82020-11-05 18:58:16 -0800151 {
William A. Kennington IIIabf17352020-12-22 21:07:11 -0800152 pack.actions->onOpen->abort();
Jason Lingc78bfc82020-11-05 18:58:16 -0800153 }
154 pack.blobState = static_cast<blobs::StateFlags>(0);
155 sessionToBlob.erase(session);
156 return true;
157 }
158 catch (const std::out_of_range& e)
159 {
160 return false;
161 }
162}
163} // namespace ipmi_flash