| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 1 | #include "version_handler.hpp" | 
|  | 2 |  | 
|  | 3 | #include <stdexcept> | 
| William A. Kennington III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 4 | #include <utility> | 
|  | 5 | #include <vector> | 
|  | 6 |  | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 7 | namespace ipmi_flash | 
|  | 8 | { | 
| William A. Kennington III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 9 |  | 
|  | 10 | VersionBlobHandler::VersionBlobHandler( | 
|  | 11 | std::vector<HandlerConfig<ActionPack>>&& configs) | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 12 | { | 
| William A. Kennington III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 13 | for (auto& config : configs) | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 14 | { | 
| William A. Kennington III | b45eb5e | 2020-12-23 11:47:05 -0800 | [diff] [blame] | 15 | 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 III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 20 | { | 
|  | 21 | fprintf(stderr, "Ignoring duplicate config for %s\n", | 
| William A. Kennington III | b45eb5e | 2020-12-23 11:47:05 -0800 | [diff] [blame] | 22 | info->blobId.c_str()); | 
| William A. Kennington III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 23 | } | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 24 | } | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 25 | } | 
|  | 26 |  | 
|  | 27 | bool VersionBlobHandler::canHandleBlob(const std::string& path) | 
|  | 28 | { | 
| William A. Kennington III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 29 | return blobInfoMap.find(path) != blobInfoMap.end(); | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 30 | } | 
|  | 31 |  | 
|  | 32 | std::vector<std::string> VersionBlobHandler::getBlobIds() | 
|  | 33 | { | 
| William A. Kennington III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 34 | std::vector<std::string> ret; | 
|  | 35 | for (const auto& [key, _] : blobInfoMap) | 
|  | 36 | { | 
| William A. Kennington III | b45eb5e | 2020-12-23 11:47:05 -0800 | [diff] [blame] | 37 | ret.emplace_back(key); | 
| William A. Kennington III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 38 | } | 
|  | 39 | return ret; | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 40 | } | 
|  | 41 |  | 
|  | 42 | /** | 
|  | 43 | * deleteBlob - does nothing, always fails | 
|  | 44 | */ | 
|  | 45 | bool VersionBlobHandler::deleteBlob(const std::string& path) | 
|  | 46 | { | 
|  | 47 | return false; | 
|  | 48 | } | 
|  | 49 |  | 
|  | 50 | bool 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 |  | 
|  | 59 | bool VersionBlobHandler::open(uint16_t session, uint16_t flags, | 
|  | 60 | const std::string& path) | 
|  | 61 | { | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 62 | /* 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 Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 69 | return false; | 
|  | 70 | } | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 71 |  | 
| William A. Kennington III | b45eb5e | 2020-12-23 11:47:05 -0800 | [diff] [blame] | 72 | auto& v = *blobInfoMap.at(path); | 
| William A. Kennington III | fbf4c53 | 2020-12-23 11:49:03 -0800 | [diff] [blame^] | 73 | sessionToBlob[session] = &v; | 
| William A. Kennington III | b45eb5e | 2020-12-23 11:47:05 -0800 | [diff] [blame] | 74 |  | 
|  | 75 | if (v.blobState == blobs::StateFlags::open_read) | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 76 | { | 
| William A. Kennington III | b45eb5e | 2020-12-23 11:47:05 -0800 | [diff] [blame] | 77 | fprintf(stderr, "open %s fail: blob already opened for read\n", | 
|  | 78 | path.c_str()); | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 79 | cleanup(session); | 
|  | 80 | return false; | 
|  | 81 | } | 
| William A. Kennington III | b45eb5e | 2020-12-23 11:47:05 -0800 | [diff] [blame] | 82 | 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 Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 90 | } | 
|  | 91 |  | 
|  | 92 | std::vector<uint8_t> VersionBlobHandler::read(uint16_t session, uint32_t offset, | 
|  | 93 | uint32_t requestedSize) | 
|  | 94 | { | 
| William A. Kennington III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 95 | BlobInfo* pack; | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 96 | try | 
|  | 97 | { | 
| William A. Kennington III | b45eb5e | 2020-12-23 11:47:05 -0800 | [diff] [blame] | 98 | pack = sessionToBlob.at(session); | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 99 | } | 
|  | 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 III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 107 | if (pack->actions->onOpen->status() != ActionStatus::success) | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 108 | { | 
|  | 109 | fprintf(stderr, "read failed: onOpen trigger not successful\n"); | 
|  | 110 | return {}; | 
|  | 111 | } | 
| William A. Kennington III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 112 | if (!pack->handler->open("don't care", std::ios::in)) | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 113 | { | 
|  | 114 | fprintf(stderr, "read failed: file open unsuccessful blob=%s\n", | 
| William A. Kennington III | b45eb5e | 2020-12-23 11:47:05 -0800 | [diff] [blame] | 115 | pack->blobId.c_str()); | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 116 | return {}; | 
|  | 117 | } | 
| William A. Kennington III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 118 | auto d = pack->handler->read(offset, requestedSize); | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 119 | if (!d) | 
|  | 120 | { | 
|  | 121 | fprintf(stderr, "read failed: unable to read file for blob %s\n", | 
| William A. Kennington III | b45eb5e | 2020-12-23 11:47:05 -0800 | [diff] [blame] | 122 | pack->blobId.c_str()); | 
| William A. Kennington III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 123 | pack->handler->close(); | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 124 | return {}; | 
|  | 125 | } | 
| William A. Kennington III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 126 | pack->handler->close(); | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 127 | return *d; | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | bool VersionBlobHandler::close(uint16_t session) | 
|  | 131 | { | 
|  | 132 | return cleanup(session); | 
|  | 133 | } | 
|  | 134 |  | 
|  | 135 | bool VersionBlobHandler::stat(uint16_t session, blobs::BlobMeta* meta) | 
|  | 136 | { | 
|  | 137 | return false; | 
|  | 138 | } | 
|  | 139 |  | 
|  | 140 | bool VersionBlobHandler::expire(uint16_t session) | 
|  | 141 | { | 
|  | 142 | return cleanup(session); | 
|  | 143 | } | 
|  | 144 |  | 
|  | 145 | bool VersionBlobHandler::cleanup(uint16_t session) | 
|  | 146 | { | 
|  | 147 | try | 
|  | 148 | { | 
| William A. Kennington III | b45eb5e | 2020-12-23 11:47:05 -0800 | [diff] [blame] | 149 | auto& pack = *sessionToBlob.at(session); | 
| William A. Kennington III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 150 | if (pack.actions->onOpen->status() == ActionStatus::running) | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 151 | { | 
| William A. Kennington III | abf1735 | 2020-12-22 21:07:11 -0800 | [diff] [blame] | 152 | pack.actions->onOpen->abort(); | 
| Jason Ling | c78bfc8 | 2020-11-05 18:58:16 -0800 | [diff] [blame] | 153 | } | 
|  | 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 |