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