1fb299fa2Sopenharmony_ci/* 2fb299fa2Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at 6fb299fa2Sopenharmony_ci * 7fb299fa2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb299fa2Sopenharmony_ci * 9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and 13fb299fa2Sopenharmony_ci * limitations under the License. 14fb299fa2Sopenharmony_ci */ 15fb299fa2Sopenharmony_ci#include "pkg_zipfile.h" 16fb299fa2Sopenharmony_ci#include <ctime> 17fb299fa2Sopenharmony_ci#include <limits> 18fb299fa2Sopenharmony_ci#include "dump.h" 19fb299fa2Sopenharmony_ci#include "pkg_algorithm.h" 20fb299fa2Sopenharmony_ci#include "pkg_manager.h" 21fb299fa2Sopenharmony_ci#include "pkg_stream.h" 22fb299fa2Sopenharmony_ci#include "zip_pkg_parse.h" 23fb299fa2Sopenharmony_ci#include "zlib.h" 24fb299fa2Sopenharmony_ci 25fb299fa2Sopenharmony_cinamespace Hpackage { 26fb299fa2Sopenharmony_ciconstexpr uint32_t TM_YEAR_BITS = 9; 27fb299fa2Sopenharmony_ciconstexpr uint32_t TM_MON_BITS = 5; 28fb299fa2Sopenharmony_ciconstexpr uint32_t TM_MIN_BITS = 5; 29fb299fa2Sopenharmony_ciconstexpr uint32_t TM_HOUR_BITS = 11; 30fb299fa2Sopenharmony_ciconstexpr uint32_t BIG_SIZE_HEADER = 20; 31fb299fa2Sopenharmony_ciconstexpr uint32_t START_YEAR = 1900; 32fb299fa2Sopenharmony_ciconstexpr uint32_t MAX_FILE_NAME = 256; 33fb299fa2Sopenharmony_ciconstexpr uint32_t LOCAL_HEADER_SIGNATURE = 0x04034b50; 34fb299fa2Sopenharmony_ciconstexpr uint32_t CENTRAL_SIGNATURE = 0x02014b50; 35fb299fa2Sopenharmony_ciconstexpr uint32_t END_CENTRAL_SIGNATURE = 0x06054b50; 36fb299fa2Sopenharmony_ciconstexpr uint32_t DATA_DESC_SIGNATURE = 0x08074b50; 37fb299fa2Sopenharmony_ciconstexpr uint32_t MAX_BUFFER_SIZE = 1024 * 64; 38fb299fa2Sopenharmony_ci// mask value that signifies that the entry has a DD 39fb299fa2Sopenharmony_ciconstexpr uint32_t GPBDD_FLAG_MASK = 0x0008; 40fb299fa2Sopenharmony_ciconstexpr uint32_t ZIP_PKG_ALIGNMENT_DEF = 1; 41fb299fa2Sopenharmony_ciconstexpr int32_t DEF_MEM_LEVEL = 8; 42fb299fa2Sopenharmony_ciconstexpr int32_t Z_STORED = 0; 43fb299fa2Sopenharmony_ci 44fb299fa2Sopenharmony_ciint32_t ZipPkgFile::AddEntry(const PkgManager::FileInfoPtr file, const PkgStreamPtr inStream) 45fb299fa2Sopenharmony_ci{ 46fb299fa2Sopenharmony_ci if (!CheckState({PKG_FILE_STATE_IDLE, PKG_FILE_STATE_WORKING}, PKG_FILE_STATE_WORKING)) { 47fb299fa2Sopenharmony_ci PKG_LOGE("Error state curr %d ", state_); 48fb299fa2Sopenharmony_ci return PKG_INVALID_STATE; 49fb299fa2Sopenharmony_ci } 50fb299fa2Sopenharmony_ci if (file == nullptr || inStream == nullptr) { 51fb299fa2Sopenharmony_ci PKG_LOGE("AddEntry failed, invalid param"); 52fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 53fb299fa2Sopenharmony_ci } 54fb299fa2Sopenharmony_ci PKG_LOGI("ZipPkgFile::AddEntry %s ", file->identity.c_str()); 55fb299fa2Sopenharmony_ci 56fb299fa2Sopenharmony_ci int32_t ret = PKG_SUCCESS; 57fb299fa2Sopenharmony_ci ZipFileEntry* entry = (ZipFileEntry*)AddPkgEntry(file->identity); 58fb299fa2Sopenharmony_ci if (entry == nullptr) { 59fb299fa2Sopenharmony_ci PKG_LOGE("Failed to create pkg node for %s", file->identity.c_str()); 60fb299fa2Sopenharmony_ci return PKG_NONE_MEMORY; 61fb299fa2Sopenharmony_ci } 62fb299fa2Sopenharmony_ci entry->Init(file, inStream); 63fb299fa2Sopenharmony_ci 64fb299fa2Sopenharmony_ci size_t encodeLen = 0; 65fb299fa2Sopenharmony_ci ret = entry->EncodeHeader(inStream, currentOffset_, encodeLen); 66fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 67fb299fa2Sopenharmony_ci PKG_LOGE("Failed to encode for %s", file->identity.c_str()); 68fb299fa2Sopenharmony_ci return ret; 69fb299fa2Sopenharmony_ci } 70fb299fa2Sopenharmony_ci currentOffset_ += encodeLen; 71fb299fa2Sopenharmony_ci ret = entry->Pack(inStream, currentOffset_, encodeLen); 72fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 73fb299fa2Sopenharmony_ci PKG_LOGE("Failed to pack for %s", file->identity.c_str()); 74fb299fa2Sopenharmony_ci return ret; 75fb299fa2Sopenharmony_ci } 76fb299fa2Sopenharmony_ci currentOffset_ += encodeLen; 77fb299fa2Sopenharmony_ci return PKG_SUCCESS; 78fb299fa2Sopenharmony_ci} 79fb299fa2Sopenharmony_ci 80fb299fa2Sopenharmony_ciint32_t ZipPkgFile::SavePackage(size_t &signOffset) 81fb299fa2Sopenharmony_ci{ 82fb299fa2Sopenharmony_ci UNUSED(signOffset); 83fb299fa2Sopenharmony_ci if (!CheckState({PKG_FILE_STATE_WORKING}, PKG_FILE_STATE_CLOSE)) { 84fb299fa2Sopenharmony_ci PKG_LOGE("error state curr %d ", state_); 85fb299fa2Sopenharmony_ci return PKG_INVALID_STATE; 86fb299fa2Sopenharmony_ci } 87fb299fa2Sopenharmony_ci int32_t ret = PKG_SUCCESS; 88fb299fa2Sopenharmony_ci size_t offset = currentOffset_; 89fb299fa2Sopenharmony_ci for (auto &it : pkgEntryMapId_) { 90fb299fa2Sopenharmony_ci ZipFileEntry* entry = (ZipFileEntry*)it.second; 91fb299fa2Sopenharmony_ci if (entry == nullptr) { 92fb299fa2Sopenharmony_ci PKG_LOGE("Failed to write CentralDirEntry"); 93fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 94fb299fa2Sopenharmony_ci } 95fb299fa2Sopenharmony_ci size_t encodeLen = 0; 96fb299fa2Sopenharmony_ci entry->EncodeCentralDirEntry(pkgStream_, offset, encodeLen); 97fb299fa2Sopenharmony_ci offset += encodeLen; 98fb299fa2Sopenharmony_ci } 99fb299fa2Sopenharmony_ci 100fb299fa2Sopenharmony_ci std::vector<uint8_t> buff(sizeof(EndCentralDir)); 101fb299fa2Sopenharmony_ci WriteLE32(buff.data() + offsetof(EndCentralDir, signature), END_CENTRAL_SIGNATURE); 102fb299fa2Sopenharmony_ci WriteLE16(buff.data() + offsetof(EndCentralDir, numDisk), 0); 103fb299fa2Sopenharmony_ci WriteLE16(buff.data() + offsetof(EndCentralDir, startDiskOfCentralDir), 0); 104fb299fa2Sopenharmony_ci WriteLE16(buff.data() + offsetof(EndCentralDir, totalEntriesInThisDisk), pkgEntryMapId_.size()); 105fb299fa2Sopenharmony_ci WriteLE16(buff.data() + offsetof(EndCentralDir, totalEntries), pkgEntryMapId_.size()); 106fb299fa2Sopenharmony_ci WriteLE32(buff.data() + offsetof(EndCentralDir, sizeOfCentralDir), offset - currentOffset_); 107fb299fa2Sopenharmony_ci WriteLE32(buff.data() + offsetof(EndCentralDir, offset), currentOffset_); 108fb299fa2Sopenharmony_ci WriteLE16(buff.data() + offsetof(EndCentralDir, commentLen), 0); 109fb299fa2Sopenharmony_ci PkgBuffer buffer(buff); 110fb299fa2Sopenharmony_ci ret = pkgStream_->Write(buffer, sizeof(EndCentralDir), offset); 111fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 112fb299fa2Sopenharmony_ci PKG_LOGE("Failed to write CentralDirEntry for %s", pkgStream_->GetFileName().c_str()); 113fb299fa2Sopenharmony_ci return ret; 114fb299fa2Sopenharmony_ci } 115fb299fa2Sopenharmony_ci currentOffset_ = offset + sizeof(EndCentralDir); 116fb299fa2Sopenharmony_ci pkgStream_->Flush(currentOffset_); 117fb299fa2Sopenharmony_ci return PKG_SUCCESS; 118fb299fa2Sopenharmony_ci} 119fb299fa2Sopenharmony_ci 120fb299fa2Sopenharmony_ciint32_t ZipPkgFile::LoadPackage(std::vector<std::string> &fileNames, PkgBuffer &buffer, 121fb299fa2Sopenharmony_ci uint32_t endDirLen, size_t endDirPos, size_t &readLen) 122fb299fa2Sopenharmony_ci{ 123fb299fa2Sopenharmony_ci size_t fileLen = pkgStream_->GetFileLength(); 124fb299fa2Sopenharmony_ci EndCentralDir endDir; 125fb299fa2Sopenharmony_ci endDir.signature = ReadLE32(buffer.buffer + offsetof(EndCentralDir, signature)); 126fb299fa2Sopenharmony_ci endDir.numDisk = ReadLE16(buffer.buffer + offsetof(EndCentralDir, numDisk)); 127fb299fa2Sopenharmony_ci endDir.startDiskOfCentralDir = ReadLE16(buffer.buffer + offsetof(EndCentralDir, startDiskOfCentralDir)); 128fb299fa2Sopenharmony_ci endDir.totalEntriesInThisDisk = ReadLE16(buffer.buffer + offsetof(EndCentralDir, totalEntriesInThisDisk)); 129fb299fa2Sopenharmony_ci endDir.totalEntries = ReadLE16(buffer.buffer + offsetof(EndCentralDir, totalEntries)); 130fb299fa2Sopenharmony_ci endDir.sizeOfCentralDir = ReadLE32(buffer.buffer + offsetof(EndCentralDir, sizeOfCentralDir)); 131fb299fa2Sopenharmony_ci endDir.offset = ReadLE32(buffer.buffer + offsetof(EndCentralDir, offset)); 132fb299fa2Sopenharmony_ci endDir.commentLen = ReadLE16(buffer.buffer + offsetof(EndCentralDir, commentLen)); 133fb299fa2Sopenharmony_ci if ((endDir.numDisk != 0) || (endDir.signature != END_CENTRAL_SIGNATURE) || 134fb299fa2Sopenharmony_ci (endDir.startDiskOfCentralDir != 0) 135fb299fa2Sopenharmony_ci#ifndef UPDATER_UT 136fb299fa2Sopenharmony_ci || (endDir.offset >= fileLen) || (endDir.totalEntriesInThisDisk != endDir.totalEntries) || 137fb299fa2Sopenharmony_ci ((endDir.offset + endDir.sizeOfCentralDir + endDirLen) > fileLen) 138fb299fa2Sopenharmony_ci#endif 139fb299fa2Sopenharmony_ci ) { 140fb299fa2Sopenharmony_ci PKG_LOGE("end dir format error %s", pkgStream_->GetFileName().c_str()); 141fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PKG_FORMAT); 142fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 143fb299fa2Sopenharmony_ci } 144fb299fa2Sopenharmony_ci size_t currentPos = endDir.offset; 145fb299fa2Sopenharmony_ci if (endDir.offset == UINT_MAX) { 146fb299fa2Sopenharmony_ci int32_t ret = pkgStream_->Read(buffer, endDirPos - sizeof(Zip64EndCentralDirLocator), 147fb299fa2Sopenharmony_ci sizeof(Zip64EndCentralDirLocator), readLen); 148fb299fa2Sopenharmony_ci uint32_t signature = ReadLE32(buffer.buffer + offsetof(Zip64EndCentralDirLocator, signature)); 149fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS || signature != 0x07064b50) { 150fb299fa2Sopenharmony_ci return ParseFileEntries(fileNames, endDir, currentPos, fileLen); 151fb299fa2Sopenharmony_ci } 152fb299fa2Sopenharmony_ci currentPos = ReadLE64(buffer.buffer + offsetof(Zip64EndCentralDirLocator, endOfCentralDirectoryRecord)); 153fb299fa2Sopenharmony_ci ret = pkgStream_->Read(buffer, currentPos, sizeof(Zip64EndCentralDirRecord), readLen); 154fb299fa2Sopenharmony_ci signature = ReadLE32(buffer.buffer + offsetof(Zip64EndCentralDirRecord, signature)); 155fb299fa2Sopenharmony_ci if (ret == PKG_SUCCESS && signature == 0x06064b50) { 156fb299fa2Sopenharmony_ci currentPos = ReadLE64(buffer.buffer + offsetof(Zip64EndCentralDirRecord, offset)); 157fb299fa2Sopenharmony_ci } 158fb299fa2Sopenharmony_ci } 159fb299fa2Sopenharmony_ci return ParseFileEntries(fileNames, endDir, currentPos, fileLen); 160fb299fa2Sopenharmony_ci} 161fb299fa2Sopenharmony_ci 162fb299fa2Sopenharmony_ciint32_t ZipPkgFile::GetFileLength(size_t &fileLen) 163fb299fa2Sopenharmony_ci{ 164fb299fa2Sopenharmony_ci if (!CheckState({PKG_FILE_STATE_IDLE}, PKG_FILE_STATE_WORKING)) { 165fb299fa2Sopenharmony_ci PKG_LOGE("Error state curr %d ", state_); 166fb299fa2Sopenharmony_ci return PKG_INVALID_STATE; 167fb299fa2Sopenharmony_ci } 168fb299fa2Sopenharmony_ci // 先从文件尾部获取 EndCentralDir 169fb299fa2Sopenharmony_ci fileLen = pkgStream_->GetFileLength(); 170fb299fa2Sopenharmony_ci if (fileLen == 0) { 171fb299fa2Sopenharmony_ci PKG_LOGE("invalid file to load"); 172fb299fa2Sopenharmony_ci return PKG_INVALID_STATE; 173fb299fa2Sopenharmony_ci } 174fb299fa2Sopenharmony_ci if (fileLen > SIZE_MAX) { 175fb299fa2Sopenharmony_ci PKG_LOGE("Invalid file len %zu to load %s", fileLen, pkgStream_->GetFileName().c_str()); 176fb299fa2Sopenharmony_ci return PKG_INVALID_FILE; 177fb299fa2Sopenharmony_ci } 178fb299fa2Sopenharmony_ci if (fileLen < static_cast<size_t>(sizeof(EndCentralDir))) { 179fb299fa2Sopenharmony_ci PKG_LOGE("Too small to be zip %s", pkgStream_->GetFileName().c_str()); 180fb299fa2Sopenharmony_ci return PKG_INVALID_FILE; 181fb299fa2Sopenharmony_ci } 182fb299fa2Sopenharmony_ci return PKG_SUCCESS; 183fb299fa2Sopenharmony_ci} 184fb299fa2Sopenharmony_ci 185fb299fa2Sopenharmony_ciint32_t ZipPkgFile::LoadPackage(std::vector<std::string>& fileNames, VerifyFunction verifier) 186fb299fa2Sopenharmony_ci{ 187fb299fa2Sopenharmony_ci UNUSED(verifier); 188fb299fa2Sopenharmony_ci PKG_LOGI("LoadPackage %s :%zu", pkgStream_->GetFileName().c_str(), pkgStream_->GetFileLength()); 189fb299fa2Sopenharmony_ci 190fb299fa2Sopenharmony_ci // 检查最后面是签名信息还是EndCentralDir 191fb299fa2Sopenharmony_ci size_t fileLen = 0; 192fb299fa2Sopenharmony_ci int32_t ret = GetFileLength(fileLen); 193fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 194fb299fa2Sopenharmony_ci PKG_LOGE("GetFileLength FAIL"); 195fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 196fb299fa2Sopenharmony_ci return ret; 197fb299fa2Sopenharmony_ci } 198fb299fa2Sopenharmony_ci size_t buffSize = sizeof(EndCentralDir); 199fb299fa2Sopenharmony_ci if (buffSize < sizeof(Zip64EndCentralDirRecord)) { 200fb299fa2Sopenharmony_ci buffSize = sizeof(Zip64EndCentralDirRecord); 201fb299fa2Sopenharmony_ci } 202fb299fa2Sopenharmony_ci 203fb299fa2Sopenharmony_ci size_t signatureLen = 0; 204fb299fa2Sopenharmony_ci uint32_t magic = 0; 205fb299fa2Sopenharmony_ci uint32_t endDirLen = sizeof(EndCentralDir); 206fb299fa2Sopenharmony_ci size_t endDirPos = fileLen - endDirLen; 207fb299fa2Sopenharmony_ci size_t readLen = 0; 208fb299fa2Sopenharmony_ci PkgBuffer buffer(nullptr, buffSize); 209fb299fa2Sopenharmony_ci ret = pkgStream_->Read(buffer, endDirPos, sizeof(EndCentralDir), readLen); 210fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 211fb299fa2Sopenharmony_ci PKG_LOGE("read EOCD struct failed %s", pkgStream_->GetFileName().c_str()); 212fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 213fb299fa2Sopenharmony_ci return ret; 214fb299fa2Sopenharmony_ci } 215fb299fa2Sopenharmony_ci magic = ReadLE32(buffer.buffer); 216fb299fa2Sopenharmony_ci if (magic != END_CENTRAL_SIGNATURE) { // 按签名处理 217fb299fa2Sopenharmony_ci ZipPkgParse zipParse; 218fb299fa2Sopenharmony_ci PkgSignComment pkgSignComment {}; 219fb299fa2Sopenharmony_ci ret = zipParse.ParseZipPkg(pkgStream_, pkgSignComment); 220fb299fa2Sopenharmony_ci signatureLen = pkgSignComment.signCommentTotalLen; 221fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 222fb299fa2Sopenharmony_ci PKG_LOGE("Parse zip package signature failed"); 223fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 224fb299fa2Sopenharmony_ci return ret; 225fb299fa2Sopenharmony_ci } 226fb299fa2Sopenharmony_ci 227fb299fa2Sopenharmony_ci endDirPos -= signatureLen; 228fb299fa2Sopenharmony_ci ret = pkgStream_->Read(buffer, endDirPos, sizeof(EndCentralDir), readLen); 229fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 230fb299fa2Sopenharmony_ci PKG_LOGE("read EOCD struct failed %s", pkgStream_->GetFileName().c_str()); 231fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 232fb299fa2Sopenharmony_ci return ret; 233fb299fa2Sopenharmony_ci } 234fb299fa2Sopenharmony_ci } 235fb299fa2Sopenharmony_ci 236fb299fa2Sopenharmony_ci return LoadPackage(fileNames, buffer, endDirLen, endDirPos, readLen); 237fb299fa2Sopenharmony_ci} 238fb299fa2Sopenharmony_ci 239fb299fa2Sopenharmony_ciint32_t ZipPkgFile::ParseFileEntries(std::vector<std::string> &fileNames, 240fb299fa2Sopenharmony_ci const EndCentralDir &endDir, size_t currentPos, size_t fileLen) 241fb299fa2Sopenharmony_ci{ 242fb299fa2Sopenharmony_ci Updater::UPDATER_INIT_RECORD; 243fb299fa2Sopenharmony_ci int32_t ret = PKG_SUCCESS; 244fb299fa2Sopenharmony_ci size_t buffLen = MAX_FILE_NAME + sizeof(LocalFileHeader) + sizeof(DataDescriptor) 245fb299fa2Sopenharmony_ci + sizeof(CentralDirEntry) + BIG_SIZE_HEADER; 246fb299fa2Sopenharmony_ci PkgBuffer buffer(buffLen); 247fb299fa2Sopenharmony_ci 248fb299fa2Sopenharmony_ci for (int32_t i = 0; i < endDir.totalEntries; i++) { 249fb299fa2Sopenharmony_ci if (fileLen <= currentPos) { 250fb299fa2Sopenharmony_ci PKG_LOGE("too small to be zip"); 251fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_FILE); 252fb299fa2Sopenharmony_ci return PKG_INVALID_FILE; 253fb299fa2Sopenharmony_ci } 254fb299fa2Sopenharmony_ci 255fb299fa2Sopenharmony_ci ZipFileEntry* entry = new ZipFileEntry(this, nodeId_++); 256fb299fa2Sopenharmony_ci if (entry == nullptr) { 257fb299fa2Sopenharmony_ci PKG_LOGE("Failed to create zip node for %s", pkgStream_->GetFileName().c_str()); 258fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_NONE_MEMORY); 259fb299fa2Sopenharmony_ci return PKG_NONE_MEMORY; 260fb299fa2Sopenharmony_ci } 261fb299fa2Sopenharmony_ci 262fb299fa2Sopenharmony_ci // 从文件中解析出文件头信息,保存在entry中 263fb299fa2Sopenharmony_ci size_t decodeLen = 0; 264fb299fa2Sopenharmony_ci ret = entry->DecodeHeader(buffer, currentPos, 0, decodeLen); 265fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 266fb299fa2Sopenharmony_ci PKG_LOGE("DecodeHeader failed"); 267fb299fa2Sopenharmony_ci delete entry; 268fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 269fb299fa2Sopenharmony_ci return ret; 270fb299fa2Sopenharmony_ci } 271fb299fa2Sopenharmony_ci 272fb299fa2Sopenharmony_ci // 保存entry文件 273fb299fa2Sopenharmony_ci pkgEntryMapId_.insert(std::pair<uint32_t, PkgEntryPtr>(entry->GetNodeId(), (PkgEntryPtr)entry)); 274fb299fa2Sopenharmony_ci pkgEntryMapFileName_.insert(std::pair<std::string, PkgEntryPtr>(entry->GetFileName(), (PkgEntryPtr)entry)); 275fb299fa2Sopenharmony_ci fileNames.push_back(entry->GetFileName()); 276fb299fa2Sopenharmony_ci 277fb299fa2Sopenharmony_ci currentPos += decodeLen; 278fb299fa2Sopenharmony_ci } 279fb299fa2Sopenharmony_ci return ret; 280fb299fa2Sopenharmony_ci} 281fb299fa2Sopenharmony_ci 282fb299fa2Sopenharmony_ciint32_t ZipFileEntry::EncodeHeader(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen) 283fb299fa2Sopenharmony_ci{ 284fb299fa2Sopenharmony_ci // 对zip包,数据和数据头信息在连续位置,使用一个打包 285fb299fa2Sopenharmony_ci encodeLen = 0; 286fb299fa2Sopenharmony_ci fileInfo_.fileInfo.headerOffset = startOffset; 287fb299fa2Sopenharmony_ci return PKG_SUCCESS; 288fb299fa2Sopenharmony_ci} 289fb299fa2Sopenharmony_ci 290fb299fa2Sopenharmony_ciint32_t ZipFileEntry::PackStream(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen, 291fb299fa2Sopenharmony_ci const PkgAlgorithm::PkgAlgorithmPtr algorithm, const PkgStreamPtr outStream) 292fb299fa2Sopenharmony_ci{ 293fb299fa2Sopenharmony_ci // 为header申请一个buff,先处理到内存,后面在写入文件 294fb299fa2Sopenharmony_ci std::vector<uint8_t> buff(MAX_FILE_NAME + sizeof(LocalFileHeader) + ZIP_PKG_ALIGNMENT_DEF); 295fb299fa2Sopenharmony_ci size_t nameLen = 0; 296fb299fa2Sopenharmony_ci PkgFileImpl::ConvertStringToBuffer(fileInfo_.fileInfo.identity, { 297fb299fa2Sopenharmony_ci buff.data() + sizeof(LocalFileHeader), buff.capacity() 298fb299fa2Sopenharmony_ci }, nameLen); 299fb299fa2Sopenharmony_ci 300fb299fa2Sopenharmony_ci size_t headerLen = nameLen + sizeof(LocalFileHeader); 301fb299fa2Sopenharmony_ci bool hasDataDesc = true; 302fb299fa2Sopenharmony_ci if (fileInfo_.method == Z_DEFLATED) { 303fb299fa2Sopenharmony_ci#ifndef UPDATER_UT 304fb299fa2Sopenharmony_ci hasDataDesc = false; 305fb299fa2Sopenharmony_ci#endif 306fb299fa2Sopenharmony_ci } 307fb299fa2Sopenharmony_ci 308fb299fa2Sopenharmony_ci fileInfo_.fileInfo.dataOffset = startOffset + headerLen; 309fb299fa2Sopenharmony_ci PkgAlgorithmContext context = { 310fb299fa2Sopenharmony_ci {0, startOffset + headerLen}, 311fb299fa2Sopenharmony_ci {fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize}, 312fb299fa2Sopenharmony_ci 0, fileInfo_.fileInfo.digestMethod 313fb299fa2Sopenharmony_ci }; 314fb299fa2Sopenharmony_ci int32_t ret = algorithm->Pack(inStream, outStream, context); 315fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 316fb299fa2Sopenharmony_ci PKG_LOGE("Failed to compress for %s", fileInfo_.fileInfo.identity.c_str()); 317fb299fa2Sopenharmony_ci return ret; 318fb299fa2Sopenharmony_ci } 319fb299fa2Sopenharmony_ci // 填充file信息,压缩后的长度和crc 320fb299fa2Sopenharmony_ci fileInfo_.fileInfo.packedSize = context.packedSize; 321fb299fa2Sopenharmony_ci crc32_ = context.crc; 322fb299fa2Sopenharmony_ci 323fb299fa2Sopenharmony_ci // 构建文件头信息,从startOffset开始 324fb299fa2Sopenharmony_ci ret = EncodeLocalFileHeader(buff.data(), sizeof(LocalFileHeader), hasDataDesc, nameLen); 325fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 326fb299fa2Sopenharmony_ci PKG_LOGE("Failed to encodeFileHeader for %s", fileInfo_.fileInfo.identity.c_str()); 327fb299fa2Sopenharmony_ci return ret; 328fb299fa2Sopenharmony_ci } 329fb299fa2Sopenharmony_ci PkgBuffer buffer(buff); 330fb299fa2Sopenharmony_ci ret = outStream->Write(buffer, headerLen, startOffset); 331fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 332fb299fa2Sopenharmony_ci PKG_LOGE("Failed to write header for %s", fileInfo_.fileInfo.identity.c_str()); 333fb299fa2Sopenharmony_ci return ret; 334fb299fa2Sopenharmony_ci } 335fb299fa2Sopenharmony_ci 336fb299fa2Sopenharmony_ci if (hasDataDesc) { // 数据描述部分 337fb299fa2Sopenharmony_ci uint32_t encodeDataDescLen = 0; 338fb299fa2Sopenharmony_ci ret = EncodeDataDescriptor(outStream, 339fb299fa2Sopenharmony_ci startOffset + headerLen + fileInfo_.fileInfo.packedSize, encodeDataDescLen); 340fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 341fb299fa2Sopenharmony_ci PKG_LOGE("Failed to encodeDataDescriptor for %s", fileInfo_.fileInfo.identity.c_str()); 342fb299fa2Sopenharmony_ci return ret; 343fb299fa2Sopenharmony_ci } 344fb299fa2Sopenharmony_ci headerLen += encodeDataDescLen; 345fb299fa2Sopenharmony_ci } 346fb299fa2Sopenharmony_ci encodeLen = headerLen + fileInfo_.fileInfo.packedSize; 347fb299fa2Sopenharmony_ci PKG_LOGI("Pack packedSize:%zu unpackedSize: %zu offset: %zu %zu", fileInfo_.fileInfo.packedSize, 348fb299fa2Sopenharmony_ci fileInfo_.fileInfo.unpackedSize, fileInfo_.fileInfo.headerOffset, fileInfo_.fileInfo.dataOffset); 349fb299fa2Sopenharmony_ci return PKG_SUCCESS; 350fb299fa2Sopenharmony_ci} 351fb299fa2Sopenharmony_ci 352fb299fa2Sopenharmony_ciint32_t ZipFileEntry::Pack(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen) 353fb299fa2Sopenharmony_ci{ 354fb299fa2Sopenharmony_ci PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(&fileInfo_.fileInfo); 355fb299fa2Sopenharmony_ci PkgStreamPtr outStream = pkgFile_->GetPkgStream(); 356fb299fa2Sopenharmony_ci if (fileInfo_.fileInfo.headerOffset != startOffset) { 357fb299fa2Sopenharmony_ci PKG_LOGE("Offset error %zu %zu %s", fileInfo_.fileInfo.headerOffset, 358fb299fa2Sopenharmony_ci startOffset, fileInfo_.fileInfo.identity.c_str()); 359fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 360fb299fa2Sopenharmony_ci } 361fb299fa2Sopenharmony_ci if (algorithm == nullptr || outStream == nullptr || inStream == nullptr) { 362fb299fa2Sopenharmony_ci PKG_LOGE("outStream or inStream null for %s", fileInfo_.fileInfo.identity.c_str()); 363fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 364fb299fa2Sopenharmony_ci } 365fb299fa2Sopenharmony_ci return PackStream(inStream, startOffset, encodeLen, algorithm, outStream); 366fb299fa2Sopenharmony_ci} 367fb299fa2Sopenharmony_ci 368fb299fa2Sopenharmony_ciint32_t ZipFileEntry::EncodeCentralDirEntry(const PkgStreamPtr stream, size_t startOffset, size_t &encodeLen) 369fb299fa2Sopenharmony_ci{ 370fb299fa2Sopenharmony_ci std::vector<uint8_t> buff(sizeof(CentralDirEntry) + MAX_FILE_NAME); 371fb299fa2Sopenharmony_ci size_t realLen = 0; 372fb299fa2Sopenharmony_ci PkgFileImpl::ConvertStringToBuffer(fileInfo_.fileInfo.identity, { 373fb299fa2Sopenharmony_ci buff.data() + sizeof(CentralDirEntry), buff.capacity() 374fb299fa2Sopenharmony_ci }, realLen); 375fb299fa2Sopenharmony_ci 376fb299fa2Sopenharmony_ci CentralDirEntry* centralDir = reinterpret_cast<CentralDirEntry*>(buff.data()); 377fb299fa2Sopenharmony_ci centralDir->signature = CENTRAL_SIGNATURE; 378fb299fa2Sopenharmony_ci centralDir->versionMade = 0; 379fb299fa2Sopenharmony_ci centralDir->versionNeeded = 0; 380fb299fa2Sopenharmony_ci if (fileInfo_.method == Z_DEFLATED) { 381fb299fa2Sopenharmony_ci centralDir->flags |= GPBDD_FLAG_MASK; 382fb299fa2Sopenharmony_ci } 383fb299fa2Sopenharmony_ci centralDir->compressionMethod = static_cast<uint16_t>(fileInfo_.method); 384fb299fa2Sopenharmony_ci centralDir->crc = crc32_; 385fb299fa2Sopenharmony_ci uint16_t date; 386fb299fa2Sopenharmony_ci uint16_t time; 387fb299fa2Sopenharmony_ci ExtraTimeAndDate(fileInfo_.fileInfo.modifiedTime, date, time); 388fb299fa2Sopenharmony_ci centralDir->modifiedDate = date; 389fb299fa2Sopenharmony_ci centralDir->modifiedTime = time; 390fb299fa2Sopenharmony_ci centralDir->compressedSize = fileInfo_.fileInfo.packedSize; 391fb299fa2Sopenharmony_ci centralDir->uncompressedSize = fileInfo_.fileInfo.unpackedSize; 392fb299fa2Sopenharmony_ci centralDir->nameSize = realLen; 393fb299fa2Sopenharmony_ci centralDir->extraSize = 0; 394fb299fa2Sopenharmony_ci centralDir->commentSize = 0; 395fb299fa2Sopenharmony_ci centralDir->diskNumStart = 0; 396fb299fa2Sopenharmony_ci centralDir->internalAttr = 0; 397fb299fa2Sopenharmony_ci centralDir->externalAttr = 0; 398fb299fa2Sopenharmony_ci centralDir->localHeaderOffset = fileInfo_.fileInfo.headerOffset; 399fb299fa2Sopenharmony_ci PkgBuffer buffer(buff); 400fb299fa2Sopenharmony_ci int32_t ret = stream->Write(buffer, sizeof(CentralDirEntry) + realLen, startOffset); 401fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 402fb299fa2Sopenharmony_ci PKG_LOGE("Failed to write CentralDirEntry for %s", fileInfo_.fileInfo.identity.c_str()); 403fb299fa2Sopenharmony_ci return ret; 404fb299fa2Sopenharmony_ci } 405fb299fa2Sopenharmony_ci encodeLen = sizeof(CentralDirEntry) + realLen; 406fb299fa2Sopenharmony_ci return PKG_SUCCESS; 407fb299fa2Sopenharmony_ci} 408fb299fa2Sopenharmony_ci 409fb299fa2Sopenharmony_ciint32_t ZipFileEntry::EncodeLocalFileHeader(uint8_t *buffer, size_t bufferLen, bool hasDataDesc, 410fb299fa2Sopenharmony_ci size_t nameLen) 411fb299fa2Sopenharmony_ci{ 412fb299fa2Sopenharmony_ci if (bufferLen < sizeof(LocalFileHeader)) { 413fb299fa2Sopenharmony_ci PKG_LOGE("invalid buffer for decode"); 414fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 415fb299fa2Sopenharmony_ci } 416fb299fa2Sopenharmony_ci 417fb299fa2Sopenharmony_ci LocalFileHeader* header = reinterpret_cast<LocalFileHeader*>(buffer); 418fb299fa2Sopenharmony_ci header->signature = LOCAL_HEADER_SIGNATURE; 419fb299fa2Sopenharmony_ci header->versionNeeded = 0; 420fb299fa2Sopenharmony_ci header->flags = 0; 421fb299fa2Sopenharmony_ci header->compressionMethod = static_cast<uint16_t>(fileInfo_.method); 422fb299fa2Sopenharmony_ci uint16_t date; 423fb299fa2Sopenharmony_ci uint16_t time; 424fb299fa2Sopenharmony_ci ExtraTimeAndDate(fileInfo_.fileInfo.modifiedTime, date, time); 425fb299fa2Sopenharmony_ci header->modifiedDate = date; 426fb299fa2Sopenharmony_ci header->modifiedTime = time; 427fb299fa2Sopenharmony_ci header->crc = crc32_; 428fb299fa2Sopenharmony_ci header->compressedSize = fileInfo_.fileInfo.packedSize; 429fb299fa2Sopenharmony_ci header->uncompressedSize = fileInfo_.fileInfo.unpackedSize; 430fb299fa2Sopenharmony_ci header->nameSize = nameLen; 431fb299fa2Sopenharmony_ci header->extraSize = 0; 432fb299fa2Sopenharmony_ci if (hasDataDesc) { 433fb299fa2Sopenharmony_ci header->flags |= GPBDD_FLAG_MASK; 434fb299fa2Sopenharmony_ci header->compressedSize = 0u; 435fb299fa2Sopenharmony_ci header->uncompressedSize = 0u; 436fb299fa2Sopenharmony_ci header->crc = 0u; 437fb299fa2Sopenharmony_ci } 438fb299fa2Sopenharmony_ci return PKG_SUCCESS; 439fb299fa2Sopenharmony_ci} 440fb299fa2Sopenharmony_ci 441fb299fa2Sopenharmony_ciint32_t ZipFileEntry::EncodeDataDescriptor(const PkgStreamPtr stream, size_t startOffset, 442fb299fa2Sopenharmony_ci uint32_t &encodeLen) const 443fb299fa2Sopenharmony_ci{ 444fb299fa2Sopenharmony_ci int32_t ret = PKG_SUCCESS; 445fb299fa2Sopenharmony_ci size_t offset = startOffset; 446fb299fa2Sopenharmony_ci DataDescriptor dataDesc = {}; 447fb299fa2Sopenharmony_ci dataDesc.signature = DATA_DESC_SIGNATURE; 448fb299fa2Sopenharmony_ci dataDesc.crc = crc32_; 449fb299fa2Sopenharmony_ci dataDesc.compressedSize = fileInfo_.fileInfo.packedSize; 450fb299fa2Sopenharmony_ci dataDesc.uncompressedSize = fileInfo_.fileInfo.unpackedSize; 451fb299fa2Sopenharmony_ci PkgBuffer buffer((uint8_t *)&dataDesc, sizeof(dataDesc)); 452fb299fa2Sopenharmony_ci ret = stream->Write(buffer, sizeof(dataDesc), offset); 453fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 454fb299fa2Sopenharmony_ci PKG_LOGE("Failed to write DataDescriptor for %s", fileInfo_.fileInfo.identity.c_str()); 455fb299fa2Sopenharmony_ci return ret; 456fb299fa2Sopenharmony_ci } 457fb299fa2Sopenharmony_ci offset += sizeof(dataDesc); 458fb299fa2Sopenharmony_ci encodeLen = offset - startOffset; 459fb299fa2Sopenharmony_ci return ret; 460fb299fa2Sopenharmony_ci} 461fb299fa2Sopenharmony_ci 462fb299fa2Sopenharmony_ciint32_t ZipFileEntry::DoDecodeCentralDirEntry(PkgBuffer &buffer, size_t &decodeLen, 463fb299fa2Sopenharmony_ci size_t currLen, uint16_t nameSize, uint16_t extraSize) 464fb299fa2Sopenharmony_ci{ 465fb299fa2Sopenharmony_ci fileInfo_.method = static_cast<int32_t>(ReadLE16(buffer.buffer + offsetof(CentralDirEntry, compressionMethod))); 466fb299fa2Sopenharmony_ci uint16_t modifiedTime = ReadLE16(buffer.buffer + offsetof(CentralDirEntry, modifiedTime)); 467fb299fa2Sopenharmony_ci uint16_t modifiedDate = ReadLE16(buffer.buffer + offsetof(CentralDirEntry, modifiedDate)); 468fb299fa2Sopenharmony_ci CombineTimeAndDate(fileInfo_.fileInfo.modifiedTime, modifiedTime, modifiedDate); 469fb299fa2Sopenharmony_ci crc32_ = ReadLE32(buffer.buffer + offsetof(CentralDirEntry, crc)); 470fb299fa2Sopenharmony_ci fileInfo_.fileInfo.packedSize = ReadLE32(buffer.buffer + offsetof(CentralDirEntry, compressedSize)); 471fb299fa2Sopenharmony_ci fileInfo_.fileInfo.unpackedSize = ReadLE32(buffer.buffer + offsetof(CentralDirEntry, uncompressedSize)); 472fb299fa2Sopenharmony_ci fileInfo_.fileInfo.headerOffset = ReadLE32(buffer.buffer + offsetof(CentralDirEntry, localHeaderOffset)); 473fb299fa2Sopenharmony_ci // 对于zip64,需要解析extra field 474fb299fa2Sopenharmony_ci decodeLen = currLen; 475fb299fa2Sopenharmony_ci if (extraSize <= 0) { 476fb299fa2Sopenharmony_ci return PKG_SUCCESS; 477fb299fa2Sopenharmony_ci } 478fb299fa2Sopenharmony_ci uint8_t* extraData = buffer.buffer + nameSize + sizeof(CentralDirEntry); 479fb299fa2Sopenharmony_ci uint16_t headerId = ReadLE16(extraData); 480fb299fa2Sopenharmony_ci if (headerId != 1) { // zip64 扩展 481fb299fa2Sopenharmony_ci return PKG_SUCCESS; 482fb299fa2Sopenharmony_ci } 483fb299fa2Sopenharmony_ci size_t unpackedSize = ReadLE64(extraData + sizeof(uint32_t)); 484fb299fa2Sopenharmony_ci size_t packedSize = ReadLE64(extraData + sizeof(uint32_t) + sizeof(uint64_t)); 485fb299fa2Sopenharmony_ci if (fileInfo_.fileInfo.packedSize == UINT_MAX || fileInfo_.fileInfo.unpackedSize == UINT_MAX) { 486fb299fa2Sopenharmony_ci fileInfo_.fileInfo.unpackedSize = 487fb299fa2Sopenharmony_ci (fileInfo_.fileInfo.unpackedSize == UINT_MAX) ? unpackedSize : fileInfo_.fileInfo.unpackedSize; 488fb299fa2Sopenharmony_ci fileInfo_.fileInfo.packedSize = 489fb299fa2Sopenharmony_ci (fileInfo_.fileInfo.packedSize == UINT_MAX) ? packedSize : fileInfo_.fileInfo.packedSize; 490fb299fa2Sopenharmony_ci fileInfo_.fileInfo.headerOffset = (fileInfo_.fileInfo.headerOffset == UINT_MAX) ? 491fb299fa2Sopenharmony_ci ReadLE64(extraData + BIG_SIZE_HEADER) : fileInfo_.fileInfo.headerOffset; 492fb299fa2Sopenharmony_ci } else if (fileInfo_.fileInfo.headerOffset == UINT_MAX) { 493fb299fa2Sopenharmony_ci fileInfo_.fileInfo.headerOffset = unpackedSize; 494fb299fa2Sopenharmony_ci } 495fb299fa2Sopenharmony_ci 496fb299fa2Sopenharmony_ci return PKG_SUCCESS; 497fb299fa2Sopenharmony_ci} 498fb299fa2Sopenharmony_ci 499fb299fa2Sopenharmony_ci/* 500fb299fa2Sopenharmony_ci 0x0001 2 bytes Tag for this "extra" block type 501fb299fa2Sopenharmony_ci Size 2 bytes Size of this "extra" block 502fb299fa2Sopenharmony_ci Original 503fb299fa2Sopenharmony_ci Size 8 bytes Original uncompressed file size 504fb299fa2Sopenharmony_ci Compressed 505fb299fa2Sopenharmony_ci Size 8 bytes Size of compressed data 506fb299fa2Sopenharmony_ci Relative Header 507fb299fa2Sopenharmony_ci Offset 8 bytes Offset of local header record 508fb299fa2Sopenharmony_ci Disk Start 509fb299fa2Sopenharmony_ci Number 4 bytes Number of the disk on which 510fb299fa2Sopenharmony_ci this file starts 511fb299fa2Sopenharmony_ci*/ 512fb299fa2Sopenharmony_ciint32_t ZipFileEntry::DecodeCentralDirEntry(PkgStreamPtr inStream, PkgBuffer &buffer, size_t currentPos, 513fb299fa2Sopenharmony_ci size_t &decodeLen) 514fb299fa2Sopenharmony_ci{ 515fb299fa2Sopenharmony_ci size_t readLen = buffer.length; 516fb299fa2Sopenharmony_ci if (readLen < sizeof(CentralDirEntry)) { 517fb299fa2Sopenharmony_ci PKG_LOGE("data not not enough %zu", readLen); 518fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 519fb299fa2Sopenharmony_ci } 520fb299fa2Sopenharmony_ci uint32_t signature = ReadLE32(buffer.buffer + offsetof(CentralDirEntry, signature)); 521fb299fa2Sopenharmony_ci if (signature != CENTRAL_SIGNATURE) { 522fb299fa2Sopenharmony_ci PKG_LOGE("Check centralDir signature failed 0x%x", signature); 523fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 524fb299fa2Sopenharmony_ci } 525fb299fa2Sopenharmony_ci uint16_t nameSize = ReadLE16(buffer.buffer + offsetof(CentralDirEntry, nameSize)); 526fb299fa2Sopenharmony_ci uint16_t extraSize = ReadLE16(buffer.buffer + offsetof(CentralDirEntry, extraSize)); 527fb299fa2Sopenharmony_ci uint16_t commentSize = ReadLE16(buffer.buffer + offsetof(CentralDirEntry, commentSize)); 528fb299fa2Sopenharmony_ci size_t currLen = sizeof(CentralDirEntry) + nameSize + extraSize + commentSize; 529fb299fa2Sopenharmony_ci if (currentPos >= (std::numeric_limits<size_t>::max() - currLen)) { 530fb299fa2Sopenharmony_ci PKG_LOGE("check centralDir len failed"); 531fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 532fb299fa2Sopenharmony_ci } 533fb299fa2Sopenharmony_ci size_t fileNameLength = nameSize; 534fb299fa2Sopenharmony_ci if (nameSize >= MAX_FILE_NAME) { 535fb299fa2Sopenharmony_ci PKG_LOGE("file name size too longer %d", nameSize); 536fb299fa2Sopenharmony_ci fileNameLength = MAX_FILE_NAME - 1; 537fb299fa2Sopenharmony_ci } 538fb299fa2Sopenharmony_ci if (readLen < sizeof(CentralDirEntry) + fileNameLength) { 539fb299fa2Sopenharmony_ci PKG_LOGE("data not not enough %zu", readLen); 540fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 541fb299fa2Sopenharmony_ci } 542fb299fa2Sopenharmony_ci fileInfo_.fileInfo.identity.assign(reinterpret_cast<char*>(buffer.buffer + sizeof(CentralDirEntry)), 543fb299fa2Sopenharmony_ci fileNameLength); 544fb299fa2Sopenharmony_ci return DoDecodeCentralDirEntry(buffer, decodeLen, currLen, nameSize, extraSize); 545fb299fa2Sopenharmony_ci} 546fb299fa2Sopenharmony_ci 547fb299fa2Sopenharmony_ciint32_t ZipFileEntry::DecodeLocalFileHeaderCheck(PkgStreamPtr inStream, PkgBuffer &data, 548fb299fa2Sopenharmony_ci size_t currentPos) 549fb299fa2Sopenharmony_ci{ 550fb299fa2Sopenharmony_ci uint16_t flags = ReadLE16(data.buffer + offsetof(LocalFileHeader, flags)); 551fb299fa2Sopenharmony_ci uint32_t crc32 = ReadLE32(data.buffer + offsetof(LocalFileHeader, crc)); 552fb299fa2Sopenharmony_ci uint32_t packedSize = ReadLE32(data.buffer + offsetof(LocalFileHeader, compressedSize)); 553fb299fa2Sopenharmony_ci uint32_t unpackedSize = ReadLE32(data.buffer + offsetof(LocalFileHeader, uncompressedSize)); 554fb299fa2Sopenharmony_ci size_t readLen = 0; 555fb299fa2Sopenharmony_ci if ((flags & GPBDD_FLAG_MASK) == GPBDD_FLAG_MASK) { 556fb299fa2Sopenharmony_ci currentPos += fileInfo_.fileInfo.packedSize; 557fb299fa2Sopenharmony_ci int ret = inStream->Read(data, currentPos, data.length, readLen); 558fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 559fb299fa2Sopenharmony_ci PKG_LOGE("parse entry read centralDir failed"); 560fb299fa2Sopenharmony_ci return ret; 561fb299fa2Sopenharmony_ci } 562fb299fa2Sopenharmony_ci if (readLen < sizeof(DataDescriptor)) { 563fb299fa2Sopenharmony_ci PKG_LOGE("data not not enough %zu", readLen); 564fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 565fb299fa2Sopenharmony_ci } 566fb299fa2Sopenharmony_ci 567fb299fa2Sopenharmony_ci uint32_t signature = ReadLE32(data.buffer + offsetof(DataDescriptor, signature)); 568fb299fa2Sopenharmony_ci if (signature != DATA_DESC_SIGNATURE) { 569fb299fa2Sopenharmony_ci PKG_LOGE("check DataDescriptor signature failed"); 570fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 571fb299fa2Sopenharmony_ci } 572fb299fa2Sopenharmony_ci crc32 = ReadLE32(data.buffer + offsetof(DataDescriptor, crc)); 573fb299fa2Sopenharmony_ci packedSize = ReadLE32(data.buffer + offsetof(DataDescriptor, compressedSize)); 574fb299fa2Sopenharmony_ci unpackedSize = ReadLE32(data.buffer + offsetof(DataDescriptor, uncompressedSize)); 575fb299fa2Sopenharmony_ci } 576fb299fa2Sopenharmony_ci PKG_LOGI("DecodeLocalFileHeaderCheck: packedSize: %zu unpackedSize: %zu", packedSize, unpackedSize); 577fb299fa2Sopenharmony_ci if (crc32_ != crc32) { 578fb299fa2Sopenharmony_ci PKG_LOGE("check crc %u %u failed", crc32_, crc32); 579fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 580fb299fa2Sopenharmony_ci } 581fb299fa2Sopenharmony_ci return PKG_SUCCESS; 582fb299fa2Sopenharmony_ci} 583fb299fa2Sopenharmony_ci 584fb299fa2Sopenharmony_ciint32_t ZipFileEntry::DecodeLocalFileHeader(PkgStreamPtr inStream, PkgBuffer &data, size_t currentPos, 585fb299fa2Sopenharmony_ci size_t &decodeLen) 586fb299fa2Sopenharmony_ci{ 587fb299fa2Sopenharmony_ci size_t readLen = 0; 588fb299fa2Sopenharmony_ci int32_t ret = inStream->Read(data, currentPos, data.length, readLen); 589fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 590fb299fa2Sopenharmony_ci PKG_LOGE("parse entry read centralDir failed"); 591fb299fa2Sopenharmony_ci return ret; 592fb299fa2Sopenharmony_ci } 593fb299fa2Sopenharmony_ci if (readLen < sizeof(LocalFileHeader)) { 594fb299fa2Sopenharmony_ci PKG_LOGE("data not not enough %zu", readLen); 595fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 596fb299fa2Sopenharmony_ci } 597fb299fa2Sopenharmony_ci uint32_t signature = ReadLE32(data.buffer + offsetof(LocalFileHeader, signature)); 598fb299fa2Sopenharmony_ci if (signature != LOCAL_HEADER_SIGNATURE) { 599fb299fa2Sopenharmony_ci PKG_LOGE("check localHeader signature failed"); 600fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 601fb299fa2Sopenharmony_ci } 602fb299fa2Sopenharmony_ci 603fb299fa2Sopenharmony_ci uint16_t nameSize = ReadLE16(data.buffer + offsetof(LocalFileHeader, nameSize)); 604fb299fa2Sopenharmony_ci uint16_t extraSize = ReadLE16(data.buffer + offsetof(LocalFileHeader, extraSize)); 605fb299fa2Sopenharmony_ci size_t currLen = sizeof(LocalFileHeader) + nameSize + extraSize; 606fb299fa2Sopenharmony_ci if (currentPos >= (std::numeric_limits<size_t>::max() - currLen)) { 607fb299fa2Sopenharmony_ci PKG_LOGE("check centralDir len failed"); 608fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 609fb299fa2Sopenharmony_ci } 610fb299fa2Sopenharmony_ci size_t fileNameLength = (nameSize >= MAX_FILE_NAME) ? MAX_FILE_NAME - 1 : nameSize; 611fb299fa2Sopenharmony_ci if (readLen < sizeof(LocalFileHeader) + fileNameLength) { 612fb299fa2Sopenharmony_ci PKG_LOGE("data not not enough %zu", readLen); 613fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 614fb299fa2Sopenharmony_ci } 615fb299fa2Sopenharmony_ci std::string fileName(reinterpret_cast<char*>(data.buffer + sizeof(LocalFileHeader)), fileNameLength); 616fb299fa2Sopenharmony_ci uint16_t compressionMethod = ReadLE16(data.buffer + offsetof(LocalFileHeader, compressionMethod)); 617fb299fa2Sopenharmony_ci fileInfo_.method = static_cast<int32_t>(compressionMethod); 618fb299fa2Sopenharmony_ci fileInfo_.level = Z_BEST_COMPRESSION; 619fb299fa2Sopenharmony_ci fileInfo_.windowBits = -MAX_WBITS; 620fb299fa2Sopenharmony_ci fileInfo_.memLevel = DEF_MEM_LEVEL; 621fb299fa2Sopenharmony_ci fileInfo_.strategy = Z_DEFAULT_STRATEGY; 622fb299fa2Sopenharmony_ci if (fileInfo_.fileInfo.identity.compare(fileName)) { 623fb299fa2Sopenharmony_ci PKG_LOGE("check file name %s %s failed", fileInfo_.fileInfo.identity.c_str(), fileName.c_str()); 624fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 625fb299fa2Sopenharmony_ci } 626fb299fa2Sopenharmony_ci fileName_.assign(fileInfo_.fileInfo.identity); 627fb299fa2Sopenharmony_ci decodeLen = currLen; 628fb299fa2Sopenharmony_ci 629fb299fa2Sopenharmony_ci // 检查解析的是否正确 630fb299fa2Sopenharmony_ci ret = DecodeLocalFileHeaderCheck(inStream, data, currentPos + currLen); 631fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 632fb299fa2Sopenharmony_ci return ret; 633fb299fa2Sopenharmony_ci } 634fb299fa2Sopenharmony_ci return PKG_SUCCESS; 635fb299fa2Sopenharmony_ci} 636fb299fa2Sopenharmony_ci 637fb299fa2Sopenharmony_ciint32_t ZipFileEntry::Stored(const PkgStreamPtr inStream, const PkgStreamPtr outStream, 638fb299fa2Sopenharmony_ci PkgAlgorithmContext &context) 639fb299fa2Sopenharmony_ci{ 640fb299fa2Sopenharmony_ci size_t start = 0; 641fb299fa2Sopenharmony_ci size_t startWrite = 0; 642fb299fa2Sopenharmony_ci size_t remainSize = context.packedSize; 643fb299fa2Sopenharmony_ci while (remainSize > 0) { 644fb299fa2Sopenharmony_ci PkgBuffer buffer(MAX_BUFFER_SIZE); 645fb299fa2Sopenharmony_ci size_t readLen = (remainSize > buffer.length) ? buffer.length : remainSize; 646fb299fa2Sopenharmony_ci int32_t ret = inStream->Read(buffer, context.srcOffset, readLen, start); 647fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 648fb299fa2Sopenharmony_ci PKG_LOGE("read buffer from inStream failed"); 649fb299fa2Sopenharmony_ci return ret; 650fb299fa2Sopenharmony_ci } 651fb299fa2Sopenharmony_ci ret = outStream->Write(buffer, readLen, startWrite); 652fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 653fb299fa2Sopenharmony_ci PKG_LOGE("write buffer in outStream failed"); 654fb299fa2Sopenharmony_ci return ret; 655fb299fa2Sopenharmony_ci } 656fb299fa2Sopenharmony_ci startWrite += readLen; 657fb299fa2Sopenharmony_ci remainSize -= readLen; 658fb299fa2Sopenharmony_ci } 659fb299fa2Sopenharmony_ci return PKG_SUCCESS; 660fb299fa2Sopenharmony_ci} 661fb299fa2Sopenharmony_ci 662fb299fa2Sopenharmony_ciint32_t ZipFileEntry::Unpack(PkgStreamPtr outStream) 663fb299fa2Sopenharmony_ci{ 664fb299fa2Sopenharmony_ci PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(&fileInfo_.fileInfo); 665fb299fa2Sopenharmony_ci if (algorithm == nullptr) { 666fb299fa2Sopenharmony_ci PKG_LOGE("ZipFileEntry::Unpack : can not algorithm for %s", fileInfo_.fileInfo.identity.c_str()); 667fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 668fb299fa2Sopenharmony_ci } 669fb299fa2Sopenharmony_ci 670fb299fa2Sopenharmony_ci PkgStreamPtr inStream = pkgFile_->GetPkgStream(); 671fb299fa2Sopenharmony_ci if (outStream == nullptr || inStream == nullptr) { 672fb299fa2Sopenharmony_ci PKG_LOGE("ZipFileEntry::Unpack : outStream or inStream null for %s", fileInfo_.fileInfo.identity.c_str()); 673fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 674fb299fa2Sopenharmony_ci } 675fb299fa2Sopenharmony_ci PkgAlgorithmContext context = { 676fb299fa2Sopenharmony_ci {this->fileInfo_.fileInfo.dataOffset, 0}, 677fb299fa2Sopenharmony_ci {fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize}, 678fb299fa2Sopenharmony_ci crc32_, fileInfo_.fileInfo.digestMethod 679fb299fa2Sopenharmony_ci }; 680fb299fa2Sopenharmony_ci int32_t ret = PKG_SUCCESS; 681fb299fa2Sopenharmony_ci switch (fileInfo_.method) { 682fb299fa2Sopenharmony_ci case Z_DEFLATED: 683fb299fa2Sopenharmony_ci ret = algorithm->Unpack(inStream, outStream, context); 684fb299fa2Sopenharmony_ci break; 685fb299fa2Sopenharmony_ci case Z_STORED: 686fb299fa2Sopenharmony_ci ret = Stored(inStream, outStream, context); 687fb299fa2Sopenharmony_ci break; 688fb299fa2Sopenharmony_ci default: 689fb299fa2Sopenharmony_ci ret = PKG_INVALID_PARAM; 690fb299fa2Sopenharmony_ci break; 691fb299fa2Sopenharmony_ci } 692fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 693fb299fa2Sopenharmony_ci PKG_LOGE("Failed to decompress for %s", fileInfo_.fileInfo.identity.c_str()); 694fb299fa2Sopenharmony_ci return ret; 695fb299fa2Sopenharmony_ci } 696fb299fa2Sopenharmony_ci PKG_LOGI("packedSize: %zu unpackedSize: %zu offset header: %zu data: %zu", fileInfo_.fileInfo.packedSize, 697fb299fa2Sopenharmony_ci fileInfo_.fileInfo.unpackedSize, fileInfo_.fileInfo.headerOffset, fileInfo_.fileInfo.dataOffset); 698fb299fa2Sopenharmony_ci ret = outStream->Flush(fileInfo_.fileInfo.unpackedSize); 699fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 700fb299fa2Sopenharmony_ci PKG_LOGE("Failed to Flush for %s", fileInfo_.fileInfo.identity.c_str()); 701fb299fa2Sopenharmony_ci return ret; 702fb299fa2Sopenharmony_ci } 703fb299fa2Sopenharmony_ci algorithm->UpdateFileInfo(&fileInfo_.fileInfo); 704fb299fa2Sopenharmony_ci return PKG_SUCCESS; 705fb299fa2Sopenharmony_ci} 706fb299fa2Sopenharmony_ci 707fb299fa2Sopenharmony_civoid ZipFileEntry::CombineTimeAndDate(time_t &time, uint16_t modifiedTime, uint16_t modifiedDate) const 708fb299fa2Sopenharmony_ci{ 709fb299fa2Sopenharmony_ci struct tm newTime; 710fb299fa2Sopenharmony_ci newTime.tm_year = ((modifiedDate >> TM_YEAR_BITS) & 0x7f) + START_YEAR; // 年,tm_year为int临时变量减去1900。 711fb299fa2Sopenharmony_ci newTime.tm_mon = (modifiedDate >> TM_MON_BITS) & 0xf; // 月,tm_mon为int临时变量减去1。 712fb299fa2Sopenharmony_ci newTime.tm_mday = modifiedDate & 0x1f; // 日。 713fb299fa2Sopenharmony_ci newTime.tm_hour = (modifiedTime >> TM_HOUR_BITS) & 0x1f; // 时。 714fb299fa2Sopenharmony_ci newTime.tm_min = (modifiedTime >> TM_MIN_BITS) & 0x2f; // 分。 715fb299fa2Sopenharmony_ci newTime.tm_sec = (modifiedTime << 1) & 0x1f; // 秒。 716fb299fa2Sopenharmony_ci newTime.tm_isdst = 0; // 非夏令时。 717fb299fa2Sopenharmony_ci time = mktime(&newTime); // 将tm结构体转换成time_t格式。 718fb299fa2Sopenharmony_ci} 719fb299fa2Sopenharmony_ci 720fb299fa2Sopenharmony_ciint32_t ZipFileEntry::DecodeHeader(PkgBuffer &buffer, size_t headerOffset, size_t dataOffset, 721fb299fa2Sopenharmony_ci size_t &decodeLen) 722fb299fa2Sopenharmony_ci{ 723fb299fa2Sopenharmony_ci PkgStreamPtr inStream = pkgFile_->GetPkgStream(); 724fb299fa2Sopenharmony_ci if (inStream == nullptr) { 725fb299fa2Sopenharmony_ci PKG_LOGE("outStream or inStream null for %s", fileInfo_.fileInfo.identity.c_str()); 726fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 727fb299fa2Sopenharmony_ci } 728fb299fa2Sopenharmony_ci 729fb299fa2Sopenharmony_ci if (headerOffset >= (std::numeric_limits<size_t>::max() - buffer.length)) { 730fb299fa2Sopenharmony_ci PKG_LOGE("check centralDir len failed"); 731fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 732fb299fa2Sopenharmony_ci } 733fb299fa2Sopenharmony_ci size_t readLen = 0; 734fb299fa2Sopenharmony_ci int32_t ret = inStream->Read(buffer, headerOffset, buffer.length, readLen); 735fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 736fb299fa2Sopenharmony_ci PKG_LOGE("parse entry read centralDir failed"); 737fb299fa2Sopenharmony_ci return ret; 738fb299fa2Sopenharmony_ci } 739fb299fa2Sopenharmony_ci PkgBuffer centralBuff(buffer.buffer, readLen); 740fb299fa2Sopenharmony_ci ret = DecodeCentralDirEntry(inStream, centralBuff, headerOffset, decodeLen); 741fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 742fb299fa2Sopenharmony_ci PKG_LOGE("decode CentralDir failed"); 743fb299fa2Sopenharmony_ci return ret; 744fb299fa2Sopenharmony_ci } 745fb299fa2Sopenharmony_ci 746fb299fa2Sopenharmony_ci size_t headerLen = 0; 747fb299fa2Sopenharmony_ci ret = DecodeLocalFileHeader(inStream, buffer, fileInfo_.fileInfo.headerOffset, headerLen); 748fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 749fb299fa2Sopenharmony_ci PKG_LOGE("decode LocalFileHeader failed"); 750fb299fa2Sopenharmony_ci return ret; 751fb299fa2Sopenharmony_ci } 752fb299fa2Sopenharmony_ci fileInfo_.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP; 753fb299fa2Sopenharmony_ci fileInfo_.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC; 754fb299fa2Sopenharmony_ci fileInfo_.fileInfo.dataOffset = fileInfo_.fileInfo.headerOffset + headerLen; 755fb299fa2Sopenharmony_ci PKG_LOGI("packedSize: %zu unpackedSize: %zu offset header: %zu data: %zu %s", 756fb299fa2Sopenharmony_ci fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize, 757fb299fa2Sopenharmony_ci fileInfo_.fileInfo.headerOffset, fileInfo_.fileInfo.dataOffset, fileInfo_.fileInfo.identity.c_str()); 758fb299fa2Sopenharmony_ci return PKG_SUCCESS; 759fb299fa2Sopenharmony_ci} 760fb299fa2Sopenharmony_ci 761fb299fa2Sopenharmony_ciint32_t ZipFileEntry::Init(const PkgManager::FileInfoPtr fileInfo, PkgStreamPtr inStream) 762fb299fa2Sopenharmony_ci{ 763fb299fa2Sopenharmony_ci fileInfo_.level = Z_BEST_COMPRESSION; 764fb299fa2Sopenharmony_ci fileInfo_.method = Z_DEFLATED; 765fb299fa2Sopenharmony_ci fileInfo_.windowBits = -MAX_WBITS; 766fb299fa2Sopenharmony_ci fileInfo_.memLevel = DEF_MEM_LEVEL; 767fb299fa2Sopenharmony_ci fileInfo_.strategy = Z_DEFAULT_STRATEGY; 768fb299fa2Sopenharmony_ci int32_t ret = PkgEntry::Init(&fileInfo_.fileInfo, fileInfo, inStream); 769fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 770fb299fa2Sopenharmony_ci PKG_LOGE("Failed to check input param"); 771fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 772fb299fa2Sopenharmony_ci } 773fb299fa2Sopenharmony_ci ZipFileInfo* info = (ZipFileInfo*)fileInfo; 774fb299fa2Sopenharmony_ci if (info != nullptr && info->method != -1) { 775fb299fa2Sopenharmony_ci fileInfo_.level = info->level; 776fb299fa2Sopenharmony_ci fileInfo_.memLevel = info->memLevel; 777fb299fa2Sopenharmony_ci fileInfo_.method = info->method; 778fb299fa2Sopenharmony_ci fileInfo_.strategy = info->strategy; 779fb299fa2Sopenharmony_ci fileInfo_.windowBits = info->windowBits; 780fb299fa2Sopenharmony_ci } 781fb299fa2Sopenharmony_ci return PKG_SUCCESS; 782fb299fa2Sopenharmony_ci} 783fb299fa2Sopenharmony_ci} // namespace Hpackage 784