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 16#include "pkg_lz4file.h" 17#include "pkg_algo_lz4.h" 18 19using namespace std; 20 21namespace Hpackage { 22int32_t Lz4FileEntry::Init(const PkgManager::FileInfoPtr fileInfo, PkgStreamPtr inStream) 23{ 24 int32_t ret = PkgEntry::Init(&fileInfo_.fileInfo, fileInfo, inStream); 25 if (ret != PKG_SUCCESS) { 26 PKG_LOGE("Fail to check input param"); 27 return PKG_INVALID_PARAM; 28 } 29 Lz4FileInfo *info = (Lz4FileInfo *)fileInfo; 30 if (info != nullptr) { 31 fileInfo_.compressionLevel = info->compressionLevel; 32 fileInfo_.blockIndependence = info->blockIndependence; 33 fileInfo_.blockSizeID = info->blockSizeID; 34 fileInfo_.contentChecksumFlag = info->contentChecksumFlag; 35 } 36 return PKG_SUCCESS; 37} 38 39int32_t Lz4FileEntry::EncodeHeader(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen) 40{ 41 encodeLen = 0; 42 fileInfo_.fileInfo.headerOffset = startOffset; 43 fileInfo_.fileInfo.dataOffset = startOffset; 44 return PKG_SUCCESS; 45} 46 47int32_t Lz4FileEntry::Pack(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen) 48{ 49 PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(&fileInfo_.fileInfo); 50 PkgStreamPtr outStream = pkgFile_->GetPkgStream(); 51 if (fileInfo_.fileInfo.headerOffset != startOffset) { 52 PKG_LOGE("start offset error for %s", fileInfo_.fileInfo.identity.c_str()); 53 return PKG_INVALID_PARAM; 54 } 55 if (algorithm == nullptr || outStream == nullptr || inStream == nullptr) { 56 PKG_LOGE("outStream or inStream null for %s", fileInfo_.fileInfo.identity.c_str()); 57 return PKG_INVALID_PARAM; 58 } 59 fileInfo_.fileInfo.dataOffset = startOffset; 60 PkgAlgorithmContext context = { 61 {0, startOffset}, 62 {fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize}, 63 0, fileInfo_.fileInfo.digestMethod 64 }; 65 int32_t ret = algorithm->Pack(inStream, outStream, context); 66 if (ret != PKG_SUCCESS) { 67 PKG_LOGE("Fail Compress for %s", fileInfo_.fileInfo.identity.c_str()); 68 return ret; 69 } 70 fileInfo_.fileInfo.packedSize = context.packedSize; 71 encodeLen = fileInfo_.fileInfo.packedSize; 72 PKG_LOGI("Pack packedSize:%zu unpackedSize: %zu offset: %zu %zu", fileInfo_.fileInfo.packedSize, 73 fileInfo_.fileInfo.unpackedSize, fileInfo_.fileInfo.headerOffset, fileInfo_.fileInfo.dataOffset); 74 return PKG_SUCCESS; 75} 76 77int32_t Lz4FileEntry::Unpack(PkgStreamPtr outStream) 78{ 79 PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(&fileInfo_.fileInfo); 80 if (algorithm == nullptr) { 81 PKG_LOGE("Lz4FileEntry::Unpack : can not algorithm for %s", fileInfo_.fileInfo.identity.c_str()); 82 return PKG_INVALID_PARAM; 83 } 84 85 PkgStreamPtr inStream = pkgFile_->GetPkgStream(); 86 if (outStream == nullptr || inStream == nullptr) { 87 PKG_LOGE("Lz4FileEntry::Unpack : outStream or inStream null for %s", fileInfo_.fileInfo.identity.c_str()); 88 return PKG_INVALID_PARAM; 89 } 90 PkgAlgorithmContext context = { 91 {fileInfo_.fileInfo.dataOffset, 0}, 92 {fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize}, 93 0, fileInfo_.fileInfo.digestMethod 94 }; 95 int32_t ret = algorithm->Unpack(inStream, outStream, context); 96 if (ret != PKG_SUCCESS) { 97 PKG_LOGE("Failed decompress for %s", fileInfo_.fileInfo.identity.c_str()); 98 return ret; 99 } 100 fileInfo_.fileInfo.packedSize = context.packedSize; 101 fileInfo_.fileInfo.unpackedSize = context.unpackedSize; 102 PKG_LOGI("packedSize: %zu unpackedSize: %zu offset header: %zu data: %zu", fileInfo_.fileInfo.packedSize, 103 fileInfo_.fileInfo.unpackedSize, fileInfo_.fileInfo.headerOffset, fileInfo_.fileInfo.dataOffset); 104 outStream->Flush(fileInfo_.fileInfo.unpackedSize); 105 algorithm->UpdateFileInfo(&fileInfo_.fileInfo); 106 return PKG_SUCCESS; 107} 108 109int32_t Lz4FileEntry::DecodeHeader(PkgBuffer &buffer, size_t headerOffset, size_t dataOffset, 110 size_t &decodeLen) 111{ 112 fileInfo_.fileInfo.identity = "lz4_"; 113 fileInfo_.fileInfo.identity.append(std::to_string(nodeId_)); 114 fileName_ = fileInfo_.fileInfo.identity; 115 fileInfo_.fileInfo.digestMethod = PKG_DIGEST_TYPE_NONE; 116 uint32_t magicNumber = ReadLE32(buffer.buffer); 117 if (magicNumber == PkgAlgorithmLz4::LZ4S_MAGIC_NUMBER) { 118 fileInfo_.fileInfo.packMethod = PKG_COMPRESS_METHOD_LZ4; 119 } else if (magicNumber == PkgAlgorithmLz4::LZ4B_MAGIC_NUMBER) { 120 fileInfo_.fileInfo.packMethod = PKG_COMPRESS_METHOD_LZ4_BLOCK; 121 } 122 fileInfo_.fileInfo.headerOffset = headerOffset; 123 fileInfo_.fileInfo.dataOffset = dataOffset; 124 fileInfo_.fileInfo.unpackedSize = pkgFile_->GetPkgStream()->GetFileLength(); 125 fileInfo_.fileInfo.packedSize = pkgFile_->GetPkgStream()->GetFileLength(); 126 return PKG_SUCCESS; 127} 128 129int32_t Lz4PkgFile::AddEntry(const PkgManager::FileInfoPtr file, const PkgStreamPtr inStream) 130{ 131 if (file == nullptr || inStream == nullptr) { 132 PKG_LOGE("Fail to check input param"); 133 return PKG_INVALID_PARAM; 134 } 135 if (!CheckState({ PKG_FILE_STATE_IDLE, PKG_FILE_STATE_WORKING }, PKG_FILE_STATE_CLOSE)) { 136 PKG_LOGE("error state curr %d ", state_); 137 return PKG_INVALID_STATE; 138 } 139 PKG_LOGI("Add file %s to package", file->identity.c_str()); 140 141 Lz4FileEntry *entry = static_cast<Lz4FileEntry *>(AddPkgEntry(file->identity)); 142 if (entry == nullptr) { 143 PKG_LOGE("Fail create pkg node for %s", file->identity.c_str()); 144 return PKG_NONE_MEMORY; 145 } 146 int32_t ret = entry->Init(file, inStream); 147 if (ret != PKG_SUCCESS) { 148 PKG_LOGE("Fail init entry for %s", file->identity.c_str()); 149 return ret; 150 } 151 152 size_t encodeLen = 0; 153 ret = entry->EncodeHeader(inStream, currentOffset_, encodeLen); 154 if (ret != PKG_SUCCESS) { 155 PKG_LOGE("Fail encode header for %s", file->identity.c_str()); 156 return ret; 157 } 158 currentOffset_ += encodeLen; 159 ret = entry->Pack(inStream, currentOffset_, encodeLen); 160 if (ret != PKG_SUCCESS) { 161 PKG_LOGE("Fail Pack for %s", file->identity.c_str()); 162 return ret; 163 } 164 currentOffset_ += encodeLen; 165 PKG_LOGI("offset:%zu ", currentOffset_); 166 pkgStream_->Flush(currentOffset_); 167 return PKG_SUCCESS; 168} 169 170int32_t Lz4PkgFile::SavePackage(size_t &offset) 171{ 172 AddSignData(pkgInfo_.digestMethod, currentOffset_, offset); 173 return PKG_SUCCESS; 174} 175 176int32_t Lz4PkgFile::LoadPackage(std::vector<std::string> &fileNames, VerifyFunction verifier) 177{ 178 UNUSED(verifier); 179 if (!CheckState({ PKG_FILE_STATE_IDLE }, PKG_FILE_STATE_WORKING)) { 180 PKG_LOGE("error state curr %d ", state_); 181 return PKG_INVALID_STATE; 182 } 183 PKG_LOGI("LoadPackage %s ", pkgStream_->GetFileName().c_str()); 184 185 size_t srcOffset = 0; 186 size_t readLen = 0; 187 PkgBuffer buffer(nullptr, sizeof(PkgAlgorithmLz4::LZ4B_MAGIC_NUMBER)); 188 int32_t ret = pkgStream_->Read(buffer, srcOffset, buffer.length, readLen); 189 if (ret != PKG_SUCCESS) { 190 PKG_LOGE("Fail to read buffer"); 191 return ret; 192 } 193 if (readLen != sizeof(PkgAlgorithmLz4::LZ4B_MAGIC_NUMBER)) { 194 PKG_LOGE("Fail to read buffer"); 195 return PKG_LZ4_FINISH; 196 } 197 198 srcOffset += sizeof(PkgAlgorithmLz4::LZ4B_MAGIC_NUMBER); 199 uint32_t magicNumber = ReadLE32(buffer.buffer); 200 PKG_LOGI("LoadPackage magic 0x%x", magicNumber); 201 ret = PKG_INVALID_FILE; 202 if (magicNumber == PkgAlgorithmLz4::LZ4S_MAGIC_NUMBER || 203 magicNumber == PkgAlgorithmLz4::LZ4B_MAGIC_NUMBER) { 204 Lz4FileEntry *entry = new Lz4FileEntry(this, nodeId_++); 205 if (entry == nullptr) { 206 PKG_LOGE("Fail create upgrade node for %s", pkgStream_->GetFileName().c_str()); 207 return PKG_LZ4_FINISH; 208 } 209 ret = entry->DecodeHeader(buffer, 0, srcOffset, readLen); 210 211 // 保存entry文件 212 pkgEntryMapId_.insert(std::pair<uint32_t, PkgEntryPtr>(entry->GetNodeId(), entry)); 213 pkgEntryMapFileName_.insert(std::pair<std::string, PkgEntryPtr>(entry->GetFileName(), entry)); 214 fileNames.push_back(entry->GetFileName()); 215 } 216 return ret; 217} 218} // namespace Hpackage 219