1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include "pkg_pkgfile.h" 16#include <ctime> 17#include <limits> 18#include <memory> 19#include "dump.h" 20#include "pkg_gzipfile.h" 21#include "pkg_lz4file.h" 22#include "pkg_stream.h" 23#include "pkg_upgradefile.h" 24#include "pkg_utils.h" 25#include "pkg_zipfile.h" 26 27namespace Hpackage { 28PkgFileImpl::~PkgFileImpl() 29{ 30 auto iter = pkgEntryMapId_.begin(); 31 while (iter != pkgEntryMapId_.end()) { 32 auto entry = iter->second; 33 delete entry; 34 iter = pkgEntryMapId_.erase(iter); 35 } 36 pkgEntryMapId_.clear(); 37 pkgEntryMapFileName_.clear(); 38 PkgManager::StreamPtr tmpStream = pkgStream_; 39 pkgManager_->ClosePkgStream(tmpStream); 40} 41 42PkgEntryPtr PkgFileImpl::AddPkgEntry(const std::string &fileName) 43{ 44 uint32_t nodeId = ++nodeId_; 45 PkgEntryPtr entry = nullptr; 46 switch (type_) { 47 case PKG_TYPE_UPGRADE: 48 entry = new UpgradeFileEntry(this, nodeId); 49 break; 50 case PKG_TYPE_ZIP: 51 entry = new ZipFileEntry(this, nodeId); 52 break; 53 case PKG_TYPE_LZ4: { 54 entry = new Lz4FileEntry(this, nodeId); 55 break; 56 } 57 case PKG_TYPE_GZIP: { 58 entry = new GZipFileEntry(this, nodeId); 59 break; 60 } 61 default: 62 return nullptr; 63 } 64 pkgEntryMapId_.insert(std::pair<uint32_t, PkgEntryPtr>(nodeId, entry)); 65 pkgEntryMapFileName_.insert(std::pair<std::string, PkgEntryPtr>(fileName, entry)); 66 return entry; 67} 68 69int32_t PkgFileImpl::ExtractFile(const PkgEntryPtr node, PkgStreamPtr output) 70{ 71 PKG_LOGI("ExtractFile %s", output->GetFileName().c_str()); 72 if (!CheckState({PKG_FILE_STATE_WORKING}, PKG_FILE_STATE_WORKING)) { 73 PKG_LOGE("error state curr %d ", state_); 74 UPDATER_LAST_WORD(PKG_INVALID_STATE); 75 return PKG_INVALID_STATE; 76 } 77 auto entry = static_cast<PkgEntryPtr>(node); 78 if (entry == nullptr) { 79 PKG_LOGE("error get entry %s", pkgStream_->GetFileName().c_str()); 80 UPDATER_LAST_WORD(PKG_INVALID_PARAM); 81 return PKG_INVALID_PARAM; 82 } 83 return entry->Unpack(output); 84} 85 86PkgEntryPtr PkgFileImpl::FindPkgEntry(const std::string &fileName) 87{ 88 if (!CheckState({PKG_FILE_STATE_WORKING}, PKG_FILE_STATE_WORKING)) { 89 PKG_LOGE("error state curr %d ", state_); 90 return nullptr; 91 } 92 std::multimap<std::string, PkgEntryPtr>::iterator iter = pkgEntryMapFileName_.find(fileName); 93 if (iter != pkgEntryMapFileName_.end()) { 94 return (*iter).second; 95 } 96 return nullptr; 97} 98 99bool PkgFileImpl::CheckState(std::vector<uint32_t> states, uint32_t state) 100{ 101 bool ret = false; 102 for (auto s : states) { 103 if (state_ == s) { 104 state_ = state; 105 ret = true; 106 break; 107 } 108 } 109 return ret; 110} 111 112int32_t PkgFileImpl::ConvertBufferToString(std::string &fileName, const PkgBuffer &buffer) 113{ 114 for (uint32_t i = 0; i < buffer.length; ++i) { 115 if (buffer.buffer[i] < 32 || buffer.buffer[i] >= 127) { // 32,127 : should be printable character 116 break; 117 } 118 fileName.push_back(buffer.buffer[i]); 119 } 120 return PKG_SUCCESS; 121} 122 123int32_t PkgFileImpl::ConvertStringToBuffer(const std::string &fileName, const PkgBuffer &buffer, size_t &realLen) 124{ 125 if (buffer.length < fileName.size()) { 126 PKG_LOGE("Invalid buffer"); 127 return PKG_INVALID_PARAM; 128 } 129 for (uint32_t i = 0; i < fileName.size(); ++i) { 130 buffer.buffer[i] = static_cast<uint8_t>(fileName[i]); 131 (realLen)++; 132 } 133 return PKG_SUCCESS; 134} 135 136int32_t PkgEntry::Init(PkgManager::FileInfoPtr localFileInfo, const PkgManager::FileInfoPtr fileInfo, 137 PkgStreamPtr inStream) 138{ 139 if (localFileInfo == nullptr || fileInfo == nullptr || inStream == nullptr) { 140 PKG_LOGE("Failed to check input param"); 141 return PKG_INVALID_PARAM; 142 } 143 144 fileName_.assign(inStream->GetFileName()); 145 localFileInfo->identity.assign(fileInfo->identity); 146 localFileInfo->flags = fileInfo->flags; 147 localFileInfo->digestMethod = fileInfo->digestMethod; 148 localFileInfo->packMethod = fileInfo->packMethod; 149 localFileInfo->modifiedTime = fileInfo->modifiedTime; 150 localFileInfo->packedSize = fileInfo->packedSize; 151 localFileInfo->unpackedSize = fileInfo->unpackedSize; 152 153 // 填充file信息,默认值使用原始文件长度 154 if (localFileInfo->unpackedSize == 0) { 155 localFileInfo->unpackedSize = inStream->GetFileLength(); 156 } 157 if (localFileInfo->packedSize == 0) { 158 localFileInfo->packedSize = inStream->GetFileLength(); 159 } 160 if (localFileInfo->unpackedSize == 0) { 161 PKG_LOGE("Failed to check unpackedSize = 0"); 162 return PKG_INVALID_PARAM; 163 } 164 if (localFileInfo->modifiedTime == 0) { 165 time(&localFileInfo->modifiedTime); 166 } 167 return PKG_SUCCESS; 168} 169 170void PkgFileImpl::AddSignData(uint8_t digestMethod, size_t currOffset, size_t &signOffset) 171{ 172 signOffset = currOffset; 173 if (digestMethod == PKG_DIGEST_TYPE_NONE) { 174 return; 175 } 176 std::vector<uint8_t> buffer(SIGN_SHA256_LEN + SIGN_SHA384_LEN, 0); 177 int32_t ret = pkgStream_->Write(buffer, buffer.size(), currOffset); 178 if (ret != PKG_SUCCESS) { 179 PKG_LOGE("Fail write sign for %s", pkgStream_->GetFileName().c_str()); 180 return; 181 } 182 pkgStream_->Flush(currOffset + buffer.size()); 183 PKG_LOGI("SavePackage success file length: %zu signOffset %zu", pkgStream_->GetFileLength(), signOffset); 184} 185} // namespace Hpackage 186