1 #include "version_handler.hpp" 2 3 #include <stdexcept> 4 namespace ipmi_flash 5 { 6 std::unique_ptr<blobs::GenericBlobInterface> 7 VersionBlobHandler::create(VersionInfoMap&& versionMap) 8 { 9 std::vector<std::string> blobList; 10 for (const auto& [key, val] : versionMap) 11 { 12 blobList.push_back(key); 13 } 14 return std::make_unique<VersionBlobHandler>(std::move(blobList), 15 std::move(versionMap)); 16 } 17 18 bool VersionBlobHandler::canHandleBlob(const std::string& path) 19 { 20 return (std::find(blobIds.begin(), blobIds.end(), path) != blobIds.end()); 21 } 22 23 std::vector<std::string> VersionBlobHandler::getBlobIds() 24 { 25 return blobIds; 26 } 27 28 /** 29 * deleteBlob - does nothing, always fails 30 */ 31 bool VersionBlobHandler::deleteBlob(const std::string& path) 32 { 33 return false; 34 } 35 36 bool 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 45 bool 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 } 64 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 93 std::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 133 bool VersionBlobHandler::close(uint16_t session) 134 { 135 return cleanup(session); 136 } 137 138 bool VersionBlobHandler::stat(uint16_t session, blobs::BlobMeta* meta) 139 { 140 return false; 141 } 142 143 bool VersionBlobHandler::expire(uint16_t session) 144 { 145 return cleanup(session); 146 } 147 148 bool 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 168