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_gzipfile.h"
16fb299fa2Sopenharmony_ci#include "dump.h"
17fb299fa2Sopenharmony_ci
18fb299fa2Sopenharmony_ciusing namespace std;
19fb299fa2Sopenharmony_ci
20fb299fa2Sopenharmony_cinamespace Hpackage {
21fb299fa2Sopenharmony_ci/* gzip flag byte */
22fb299fa2Sopenharmony_ciconstexpr uint16_t HEADER_CRC = 0x02; /* bit 1 set: CRC16 for the gzip header */
23fb299fa2Sopenharmony_ciconstexpr uint16_t EXTRA_FIELD = 0x04; /* bit 2 set: extra field present */
24fb299fa2Sopenharmony_ciconstexpr uint16_t ORIG_NAME = 0x08; /* bit 3 set: original file name present */
25fb299fa2Sopenharmony_ciconstexpr uint16_t COMMENT = 0x10; /* bit 4 set: file comment present */
26fb299fa2Sopenharmony_ciconstexpr uint16_t ENCRYPTED = 0x20; /* bit 5 set: file is encrypted */
27fb299fa2Sopenharmony_ciconstexpr int32_t DEF_MEM_LEVEL = 8;
28fb299fa2Sopenharmony_ciconstexpr uint16_t GZIP_MAGIC = 0x8b1f;
29fb299fa2Sopenharmony_ciconstexpr int32_t BUFFER_SIZE = 1024;
30fb299fa2Sopenharmony_ci#ifdef SUPPORT_EXTRA_FIELD
31fb299fa2Sopenharmony_ciconstexpr int32_t EXTRA_FIELD_LEN = 20;
32fb299fa2Sopenharmony_ci#endif
33fb299fa2Sopenharmony_ciconstexpr int32_t BLOCK_SIZE = 8;
34fb299fa2Sopenharmony_ci
35fb299fa2Sopenharmony_ci/*
36fb299fa2Sopenharmony_ci    Each member has the following structure:
37fb299fa2Sopenharmony_ci     +---+---+---+---+---+---+---+---+---+---+
38fb299fa2Sopenharmony_ci     |ID1|ID2|CM |FLG|     MTIME     |XFL|OS | (more-->)
39fb299fa2Sopenharmony_ci     +---+---+---+---+---+---+---+---+---+---+
40fb299fa2Sopenharmony_ci
41fb299fa2Sopenharmony_ci    (if FLG.FEXTRA set)
42fb299fa2Sopenharmony_ci
43fb299fa2Sopenharmony_ci     +---+---+=================================+
44fb299fa2Sopenharmony_ci     | XLEN  |...XLEN bytes of "extra field"...| (more-->)
45fb299fa2Sopenharmony_ci     +---+---+=================================+
46fb299fa2Sopenharmony_ci
47fb299fa2Sopenharmony_ci    (if FLG.FNAME set)
48fb299fa2Sopenharmony_ci
49fb299fa2Sopenharmony_ci     +=========================================+
50fb299fa2Sopenharmony_ci     |...original file name, zero-terminated...| (more-->)
51fb299fa2Sopenharmony_ci     +=========================================+
52fb299fa2Sopenharmony_ci
53fb299fa2Sopenharmony_ci    (if FLG.FCOMMENT set)
54fb299fa2Sopenharmony_ci
55fb299fa2Sopenharmony_ci     +===================================+
56fb299fa2Sopenharmony_ci     |...file comment, zero-terminated...| (more-->)
57fb299fa2Sopenharmony_ci     +===================================+
58fb299fa2Sopenharmony_ci
59fb299fa2Sopenharmony_ci    (if FLG.FHCRC set)
60fb299fa2Sopenharmony_ci
61fb299fa2Sopenharmony_ci     +---+---+
62fb299fa2Sopenharmony_ci     | CRC16 |
63fb299fa2Sopenharmony_ci     +---+---+
64fb299fa2Sopenharmony_ci */
65fb299fa2Sopenharmony_civoid GZipFileEntry::GetUpGradeCompInfo(size_t &offset, PkgBuffer &buffer)
66fb299fa2Sopenharmony_ci{
67fb299fa2Sopenharmony_ci    GZipHeader *header = (GZipHeader *)buffer.buffer;
68fb299fa2Sopenharmony_ci    header->magic = GZIP_MAGIC;
69fb299fa2Sopenharmony_ci    header->method = Z_DEFLATED;
70fb299fa2Sopenharmony_ci    header->flags = 0;
71fb299fa2Sopenharmony_ci    header->mtime = fileInfo_.fileInfo.modifiedTime;
72fb299fa2Sopenharmony_ci    offset += sizeof(GZipHeader);
73fb299fa2Sopenharmony_ci#ifdef SUPPORT_EXTRA_FIELD
74fb299fa2Sopenharmony_ci    header->flags |= EXTRA_FIELD;
75fb299fa2Sopenharmony_ci    {
76fb299fa2Sopenharmony_ci        WriteLE16(buffer.buffer + offset, EXTRA_FIELD_LEN);
77fb299fa2Sopenharmony_ci        offset += sizeof(uint16_t) + EXTRA_FIELD_LEN;
78fb299fa2Sopenharmony_ci    }
79fb299fa2Sopenharmony_ci#endif
80fb299fa2Sopenharmony_ci    header->flags |= ORIG_NAME;
81fb299fa2Sopenharmony_ci    {
82fb299fa2Sopenharmony_ci        size_t fileNameLen = 0;
83fb299fa2Sopenharmony_ci        PkgFileImpl::ConvertStringToBuffer(
84fb299fa2Sopenharmony_ci            fileInfo_.fileInfo.identity, {buffer.buffer + offset, buffer.length - offset}, fileNameLen);
85fb299fa2Sopenharmony_ci        offset += fileNameLen;
86fb299fa2Sopenharmony_ci        buffer.buffer[offset] = 0;
87fb299fa2Sopenharmony_ci        offset += 1;
88fb299fa2Sopenharmony_ci    }
89fb299fa2Sopenharmony_ci#ifdef SUPPORT_EXTRA_FIELD
90fb299fa2Sopenharmony_ci    header->flags |= COMMENT;
91fb299fa2Sopenharmony_ci    {
92fb299fa2Sopenharmony_ci        size_t fileNameLen = 0;
93fb299fa2Sopenharmony_ci        PkgFileImpl::ConvertStringToBuffer(
94fb299fa2Sopenharmony_ci            fileInfo_.fileInfo.identity, {buffer.buffer + offset, buffer.length - offset}, fileNameLen);
95fb299fa2Sopenharmony_ci        offset += fileNameLen;
96fb299fa2Sopenharmony_ci        buffer.buffer[offset] = 0;
97fb299fa2Sopenharmony_ci        offset += 1;
98fb299fa2Sopenharmony_ci    }
99fb299fa2Sopenharmony_ci#endif
100fb299fa2Sopenharmony_ci    return ;
101fb299fa2Sopenharmony_ci}
102fb299fa2Sopenharmony_ci
103fb299fa2Sopenharmony_ciint32_t GZipFileEntry::EncodeHeader(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen)
104fb299fa2Sopenharmony_ci{
105fb299fa2Sopenharmony_ci    PkgStreamPtr outStream = pkgFile_->GetPkgStream();
106fb299fa2Sopenharmony_ci    if (outStream == nullptr) {
107fb299fa2Sopenharmony_ci        PKG_LOGE("Check outstream fail %s", fileInfo_.fileInfo.identity.c_str());
108fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
109fb299fa2Sopenharmony_ci    }
110fb299fa2Sopenharmony_ci    size_t offset = 0;
111fb299fa2Sopenharmony_ci    PkgBuffer buffer(BUFFER_SIZE);
112fb299fa2Sopenharmony_ci
113fb299fa2Sopenharmony_ci    GetUpGradeCompInfo(offset, buffer);
114fb299fa2Sopenharmony_ci
115fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.headerOffset = startOffset;
116fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.dataOffset = startOffset + offset;
117fb299fa2Sopenharmony_ci    int32_t ret = outStream->Write(buffer, offset, startOffset);
118fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
119fb299fa2Sopenharmony_ci        PKG_LOGE("Fail write header for %s", fileInfo_.fileInfo.identity.c_str());
120fb299fa2Sopenharmony_ci        return ret;
121fb299fa2Sopenharmony_ci    }
122fb299fa2Sopenharmony_ci    encodeLen = offset;
123fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
124fb299fa2Sopenharmony_ci}
125fb299fa2Sopenharmony_ci
126fb299fa2Sopenharmony_ciint32_t GZipFileEntry::Pack(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen)
127fb299fa2Sopenharmony_ci{
128fb299fa2Sopenharmony_ci    PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(&fileInfo_.fileInfo);
129fb299fa2Sopenharmony_ci    PkgStreamPtr outStream = pkgFile_->GetPkgStream();
130fb299fa2Sopenharmony_ci    if (fileInfo_.fileInfo.dataOffset != startOffset) {
131fb299fa2Sopenharmony_ci        PKG_LOGE("start offset error for %s", fileInfo_.fileInfo.identity.c_str());
132fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
133fb299fa2Sopenharmony_ci    }
134fb299fa2Sopenharmony_ci    if (algorithm == nullptr || outStream == nullptr || inStream == nullptr) {
135fb299fa2Sopenharmony_ci        PKG_LOGE("outStream or inStream null for %s", fileInfo_.fileInfo.identity.c_str());
136fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
137fb299fa2Sopenharmony_ci    }
138fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.dataOffset = startOffset;
139fb299fa2Sopenharmony_ci    PkgAlgorithmContext context = {
140fb299fa2Sopenharmony_ci        {0, startOffset},
141fb299fa2Sopenharmony_ci        {fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize},
142fb299fa2Sopenharmony_ci        0, fileInfo_.fileInfo.digestMethod
143fb299fa2Sopenharmony_ci    };
144fb299fa2Sopenharmony_ci    int32_t ret = algorithm->Pack(inStream, outStream, context);
145fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
146fb299fa2Sopenharmony_ci        PKG_LOGE("Fail Compress for %s", fileInfo_.fileInfo.identity.c_str());
147fb299fa2Sopenharmony_ci        return ret;
148fb299fa2Sopenharmony_ci    }
149fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.packedSize = context.packedSize;
150fb299fa2Sopenharmony_ci
151fb299fa2Sopenharmony_ci    /*
152fb299fa2Sopenharmony_ci    0   1   2   3   4   5   6   7
153fb299fa2Sopenharmony_ci    +---+---+---+---+---+---+---+---+
154fb299fa2Sopenharmony_ci    |     CRC32     |     ISIZE     |
155fb299fa2Sopenharmony_ci    +---+---+---+---+---+---+---+---+
156fb299fa2Sopenharmony_ci    */
157fb299fa2Sopenharmony_ci    PkgBuffer buffer(BLOCK_SIZE);
158fb299fa2Sopenharmony_ci    WriteLE32(buffer.buffer, context.crc);
159fb299fa2Sopenharmony_ci    WriteLE32(buffer.buffer + sizeof(uint32_t), fileInfo_.fileInfo.unpackedSize);
160fb299fa2Sopenharmony_ci    ret = outStream->Write(buffer, BLOCK_SIZE, fileInfo_.fileInfo.dataOffset + fileInfo_.fileInfo.packedSize);
161fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
162fb299fa2Sopenharmony_ci        PKG_LOGE("Fail write header for %s", fileInfo_.fileInfo.identity.c_str());
163fb299fa2Sopenharmony_ci        return ret;
164fb299fa2Sopenharmony_ci    }
165fb299fa2Sopenharmony_ci    encodeLen = fileInfo_.fileInfo.packedSize + BLOCK_SIZE;
166fb299fa2Sopenharmony_ci    PKG_LOGI("Pack packedSize:%zu unpackedSize: %zu offset: %zu %zu", fileInfo_.fileInfo.packedSize,
167fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.unpackedSize, fileInfo_.fileInfo.headerOffset, fileInfo_.fileInfo.dataOffset);
168fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
169fb299fa2Sopenharmony_ci}
170fb299fa2Sopenharmony_ci
171fb299fa2Sopenharmony_ciint32_t GZipFileEntry::CheckFileInfo(PkgAlgorithmContext context, PkgStreamPtr inStream)
172fb299fa2Sopenharmony_ci{
173fb299fa2Sopenharmony_ci    size_t readLen = 0;
174fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.packedSize = context.packedSize;
175fb299fa2Sopenharmony_ci    PkgBuffer buffer(BLOCK_SIZE); // Read last 8 bytes at the end of package
176fb299fa2Sopenharmony_ci    int32_t ret = inStream->Read(buffer, context.packedSize + fileInfo_.fileInfo.dataOffset, BLOCK_SIZE, readLen);
177fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
178fb299fa2Sopenharmony_ci        PKG_LOGE("Fail to read file %s", inStream->GetFileName().c_str());
179fb299fa2Sopenharmony_ci        return ret;
180fb299fa2Sopenharmony_ci    }
181fb299fa2Sopenharmony_ci    crc32_ = ReadLE32(buffer.buffer);
182fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.unpackedSize = ReadLE32(buffer.buffer + sizeof(uint32_t));
183fb299fa2Sopenharmony_ci    if (crc32_ != context.crc) {
184fb299fa2Sopenharmony_ci        PKG_LOGE("Crc error %u %u", crc32_, context.crc);
185fb299fa2Sopenharmony_ci        return PKG_VERIFY_FAIL;
186fb299fa2Sopenharmony_ci    }
187fb299fa2Sopenharmony_ci
188fb299fa2Sopenharmony_ci    if (fileInfo_.fileInfo.unpackedSize != context.unpackedSize) {
189fb299fa2Sopenharmony_ci        PKG_LOGE("Crc error %u %u", crc32_, context.crc);
190fb299fa2Sopenharmony_ci        return PKG_VERIFY_FAIL;
191fb299fa2Sopenharmony_ci    }
192fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
193fb299fa2Sopenharmony_ci}
194fb299fa2Sopenharmony_ci
195fb299fa2Sopenharmony_ciint32_t GZipFileEntry::Unpack(PkgStreamPtr outStream)
196fb299fa2Sopenharmony_ci{
197fb299fa2Sopenharmony_ci    PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(&fileInfo_.fileInfo);
198fb299fa2Sopenharmony_ci    if (algorithm == nullptr) {
199fb299fa2Sopenharmony_ci        PKG_LOGE("can not algorithm for %s", fileInfo_.fileInfo.identity.c_str());
200fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
201fb299fa2Sopenharmony_ci    }
202fb299fa2Sopenharmony_ci
203fb299fa2Sopenharmony_ci    PKG_LOGI("packedSize: %zu unpackedSize: %zu  offset header: %zu data: %zu", fileInfo_.fileInfo.packedSize,
204fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.unpackedSize, fileInfo_.fileInfo.headerOffset, fileInfo_.fileInfo.dataOffset);
205fb299fa2Sopenharmony_ci
206fb299fa2Sopenharmony_ci    PkgStreamPtr inStream = pkgFile_->GetPkgStream();
207fb299fa2Sopenharmony_ci    if (outStream == nullptr || inStream == nullptr) {
208fb299fa2Sopenharmony_ci        PKG_LOGE("outStream or inStream null for %s", fileInfo_.fileInfo.identity.c_str());
209fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
210fb299fa2Sopenharmony_ci    }
211fb299fa2Sopenharmony_ci
212fb299fa2Sopenharmony_ci    PkgAlgorithmContext context = {
213fb299fa2Sopenharmony_ci        {fileInfo_.fileInfo.dataOffset, 0},
214fb299fa2Sopenharmony_ci        {fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize},
215fb299fa2Sopenharmony_ci        0, fileInfo_.fileInfo.digestMethod
216fb299fa2Sopenharmony_ci    };
217fb299fa2Sopenharmony_ci    int32_t ret = algorithm->Unpack(inStream, outStream, context);
218fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
219fb299fa2Sopenharmony_ci        PKG_LOGE("Fail Decompress for %s", fileInfo_.fileInfo.identity.c_str());
220fb299fa2Sopenharmony_ci        return ret;
221fb299fa2Sopenharmony_ci    }
222fb299fa2Sopenharmony_ci
223fb299fa2Sopenharmony_ci    ret = CheckFileInfo(context, inStream);
224fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
225fb299fa2Sopenharmony_ci        PKG_LOGE("unpack failed ret is %d", ret);
226fb299fa2Sopenharmony_ci        return ret;
227fb299fa2Sopenharmony_ci    }
228fb299fa2Sopenharmony_ci
229fb299fa2Sopenharmony_ci    PKG_LOGI("packedSize: %zu unpackedSize: %zu  offset header: %zu data: %zu", fileInfo_.fileInfo.packedSize,
230fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.unpackedSize, fileInfo_.fileInfo.headerOffset, fileInfo_.fileInfo.dataOffset);
231fb299fa2Sopenharmony_ci    outStream->Flush(fileInfo_.fileInfo.unpackedSize);
232fb299fa2Sopenharmony_ci    algorithm->UpdateFileInfo(&fileInfo_.fileInfo);
233fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
234fb299fa2Sopenharmony_ci}
235fb299fa2Sopenharmony_ci
236fb299fa2Sopenharmony_civoid GZipFileEntry::DecodeHeaderCalOffset(uint8_t flags, const PkgBuffer &buffer, size_t &offset,
237fb299fa2Sopenharmony_ci    std::string &fileName) const
238fb299fa2Sopenharmony_ci{
239fb299fa2Sopenharmony_ci    if (flags & EXTRA_FIELD) {
240fb299fa2Sopenharmony_ci        uint16_t extLen = ReadLE16(buffer.buffer + offset);
241fb299fa2Sopenharmony_ci        offset += sizeof(uint16_t) + extLen;
242fb299fa2Sopenharmony_ci    }
243fb299fa2Sopenharmony_ci    if ((buffer.length > offset) && (flags & ORIG_NAME)) {
244fb299fa2Sopenharmony_ci        PkgFileImpl::ConvertBufferToString(fileName, {buffer.buffer + offset, buffer.length - offset});
245fb299fa2Sopenharmony_ci        offset += fileName.size() + 1;
246fb299fa2Sopenharmony_ci    }
247fb299fa2Sopenharmony_ci    if ((buffer.length > offset) && (flags & COMMENT)) {
248fb299fa2Sopenharmony_ci        std::string comment;
249fb299fa2Sopenharmony_ci        PkgFileImpl::ConvertBufferToString(comment, {buffer.buffer + offset, buffer.length - offset});
250fb299fa2Sopenharmony_ci        offset += comment.size() + 1;
251fb299fa2Sopenharmony_ci    }
252fb299fa2Sopenharmony_ci    if (flags & HEADER_CRC) { // Skip CRC
253fb299fa2Sopenharmony_ci        offset += sizeof(uint16_t);
254fb299fa2Sopenharmony_ci    }
255fb299fa2Sopenharmony_ci    return;
256fb299fa2Sopenharmony_ci}
257fb299fa2Sopenharmony_ci
258fb299fa2Sopenharmony_ciint32_t GZipFileEntry::DecodeHeader(PkgBuffer &buffer, size_t headerOffset, size_t dataOffset,
259fb299fa2Sopenharmony_ci    size_t &decodeLen)
260fb299fa2Sopenharmony_ci{
261fb299fa2Sopenharmony_ci    Updater::UPDATER_INIT_RECORD;
262fb299fa2Sopenharmony_ci    PkgStreamPtr inStream = pkgFile_->GetPkgStream();
263fb299fa2Sopenharmony_ci    if (inStream == nullptr || buffer.buffer == nullptr) {
264fb299fa2Sopenharmony_ci        PKG_LOGE("outStream or inStream null for %s", fileInfo_.fileInfo.identity.c_str());
265fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(PKG_INVALID_PARAM);
266fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
267fb299fa2Sopenharmony_ci    }
268fb299fa2Sopenharmony_ci    size_t offset = sizeof(GZipHeader);
269fb299fa2Sopenharmony_ci
270fb299fa2Sopenharmony_ci    uint8_t flags = *(buffer.buffer + offsetof(GZipHeader, flags));
271fb299fa2Sopenharmony_ci
272fb299fa2Sopenharmony_ci    DecodeHeaderCalOffset(flags, buffer, offset, fileName_);
273fb299fa2Sopenharmony_ci    if (fileName_.empty()) {
274fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.identity = "gzip_";
275fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.identity.append(std::to_string(nodeId_));
276fb299fa2Sopenharmony_ci        fileName_ = fileInfo_.fileInfo.identity;
277fb299fa2Sopenharmony_ci    } else {
278fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.identity = fileName_;
279fb299fa2Sopenharmony_ci    }
280fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC;
281fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.packMethod = PKG_COMPRESS_METHOD_GZIP;
282fb299fa2Sopenharmony_ci    fileInfo_.level = Z_BEST_COMPRESSION;
283fb299fa2Sopenharmony_ci    fileInfo_.method = Z_DEFLATED;
284fb299fa2Sopenharmony_ci    fileInfo_.windowBits = -MAX_WBITS;
285fb299fa2Sopenharmony_ci    fileInfo_.memLevel = DEF_MEM_LEVEL;
286fb299fa2Sopenharmony_ci    fileInfo_.strategy = Z_DEFAULT_STRATEGY;
287fb299fa2Sopenharmony_ci
288fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.headerOffset = headerOffset;
289fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.dataOffset = headerOffset + offset;
290fb299fa2Sopenharmony_ci    // Read data length here.
291fb299fa2Sopenharmony_ci    // The length read here maybe incorrect, so should adjust it
292fb299fa2Sopenharmony_ci    // when unpack.
293fb299fa2Sopenharmony_ci    size_t readLen = 0;
294fb299fa2Sopenharmony_ci    size_t blockOffset = inStream->GetFileLength() - BLOCK_SIZE;
295fb299fa2Sopenharmony_ci    int32_t ret = inStream->Read(buffer, blockOffset, buffer.length, readLen);
296fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
297fb299fa2Sopenharmony_ci        PKG_LOGE("Fail to read file %s", inStream->GetFileName().c_str());
298fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(ret);
299fb299fa2Sopenharmony_ci        return ret;
300fb299fa2Sopenharmony_ci    }
301fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.unpackedSize = ReadLE32(buffer.buffer + sizeof(uint32_t));
302fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.packedSize = blockOffset - fileInfo_.fileInfo.dataOffset;
303fb299fa2Sopenharmony_ci    PKG_LOGI("GZipFileEntry::DecodeHeader dataOffset %zu, packedSize: %zu %zu", fileInfo_.fileInfo.dataOffset,
304fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize);
305fb299fa2Sopenharmony_ci    decodeLen = offset;
306fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
307fb299fa2Sopenharmony_ci}
308fb299fa2Sopenharmony_ci
309fb299fa2Sopenharmony_ciint32_t GZipPkgFile::AddEntry(const PkgManager::FileInfoPtr file, const PkgStreamPtr inStream)
310fb299fa2Sopenharmony_ci{
311fb299fa2Sopenharmony_ci    if (file == nullptr || inStream == nullptr) {
312fb299fa2Sopenharmony_ci        PKG_LOGE("Fail to check input param");
313fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
314fb299fa2Sopenharmony_ci    }
315fb299fa2Sopenharmony_ci    if (!CheckState({PKG_FILE_STATE_IDLE, PKG_FILE_STATE_WORKING}, PKG_FILE_STATE_CLOSE)) {
316fb299fa2Sopenharmony_ci        PKG_LOGE("error state curr %d ", state_);
317fb299fa2Sopenharmony_ci        return PKG_INVALID_STATE;
318fb299fa2Sopenharmony_ci    }
319fb299fa2Sopenharmony_ci    PKG_LOGI("Add file %s to package", file->identity.c_str());
320fb299fa2Sopenharmony_ci
321fb299fa2Sopenharmony_ci    GZipFileEntry *entry = static_cast<GZipFileEntry *>(AddPkgEntry(file->identity));
322fb299fa2Sopenharmony_ci    if (entry == nullptr) {
323fb299fa2Sopenharmony_ci        PKG_LOGE("Fail create pkg node for %s", file->identity.c_str());
324fb299fa2Sopenharmony_ci        return PKG_NONE_MEMORY;
325fb299fa2Sopenharmony_ci    }
326fb299fa2Sopenharmony_ci    int32_t ret = entry->Init(file, inStream);
327fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
328fb299fa2Sopenharmony_ci        PKG_LOGE("Fail init entry for %s", file->identity.c_str());
329fb299fa2Sopenharmony_ci        return ret;
330fb299fa2Sopenharmony_ci    }
331fb299fa2Sopenharmony_ci
332fb299fa2Sopenharmony_ci    size_t encodeLen = 0;
333fb299fa2Sopenharmony_ci    ret = entry->EncodeHeader(inStream, currentOffset_, encodeLen);
334fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
335fb299fa2Sopenharmony_ci        PKG_LOGE("Fail encode header for %s", file->identity.c_str());
336fb299fa2Sopenharmony_ci        return ret;
337fb299fa2Sopenharmony_ci    }
338fb299fa2Sopenharmony_ci    currentOffset_ += encodeLen;
339fb299fa2Sopenharmony_ci    ret = entry->Pack(inStream, currentOffset_, encodeLen);
340fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
341fb299fa2Sopenharmony_ci        PKG_LOGE("Fail Pack for %s", file->identity.c_str());
342fb299fa2Sopenharmony_ci        return ret;
343fb299fa2Sopenharmony_ci    }
344fb299fa2Sopenharmony_ci    currentOffset_ += encodeLen;
345fb299fa2Sopenharmony_ci    pkgStream_->Flush(currentOffset_);
346fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
347fb299fa2Sopenharmony_ci}
348fb299fa2Sopenharmony_ci
349fb299fa2Sopenharmony_ciint32_t GZipPkgFile::SavePackage(size_t &offset)
350fb299fa2Sopenharmony_ci{
351fb299fa2Sopenharmony_ci    AddSignData(pkgInfo_.digestMethod, currentOffset_, offset);
352fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
353fb299fa2Sopenharmony_ci}
354fb299fa2Sopenharmony_ci
355fb299fa2Sopenharmony_ciint32_t GZipPkgFile::LoadPackage(std::vector<std::string> &fileNames, VerifyFunction verifier)
356fb299fa2Sopenharmony_ci{
357fb299fa2Sopenharmony_ci    UNUSED(verifier);
358fb299fa2Sopenharmony_ci    if (!CheckState({ PKG_FILE_STATE_IDLE }, PKG_FILE_STATE_WORKING)) {
359fb299fa2Sopenharmony_ci        PKG_LOGE("error state curr %d ", state_);
360fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(PKG_INVALID_STATE);
361fb299fa2Sopenharmony_ci        return PKG_INVALID_STATE;
362fb299fa2Sopenharmony_ci    }
363fb299fa2Sopenharmony_ci    PKG_LOGI("LoadPackage %s ", pkgStream_->GetFileName().c_str());
364fb299fa2Sopenharmony_ci    size_t srcOffset = 0;
365fb299fa2Sopenharmony_ci    size_t readLen = 0;
366fb299fa2Sopenharmony_ci    PkgBuffer buffer(nullptr, BUFFER_SIZE);
367fb299fa2Sopenharmony_ci    int32_t ret = pkgStream_->Read(buffer, srcOffset, buffer.length, readLen);
368fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
369fb299fa2Sopenharmony_ci        PKG_LOGE("Fail to read file %s", pkgStream_->GetFileName().c_str());
370fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(ret);
371fb299fa2Sopenharmony_ci        return ret;
372fb299fa2Sopenharmony_ci    }
373fb299fa2Sopenharmony_ci
374fb299fa2Sopenharmony_ci    GZipHeader *header = (GZipHeader *)buffer.buffer;
375fb299fa2Sopenharmony_ci    // Check magic number
376fb299fa2Sopenharmony_ci    if (header->magic != GZIP_MAGIC) {
377fb299fa2Sopenharmony_ci        PKG_LOGE("Invalid gzip file %s", pkgStream_->GetFileName().c_str());
378fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(PKG_INVALID_STATE);
379fb299fa2Sopenharmony_ci        return PKG_INVALID_FILE;
380fb299fa2Sopenharmony_ci    }
381fb299fa2Sopenharmony_ci    // Does not support encryption
382fb299fa2Sopenharmony_ci    if ((header->flags & ENCRYPTED) != 0) {
383fb299fa2Sopenharmony_ci        PKG_LOGE("Not support encrypted ");
384fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(PKG_INVALID_STATE);
385fb299fa2Sopenharmony_ci        return PKG_INVALID_FILE;
386fb299fa2Sopenharmony_ci    }
387fb299fa2Sopenharmony_ci
388fb299fa2Sopenharmony_ci    GZipFileEntry *entry = new GZipFileEntry(this, nodeId_++);
389fb299fa2Sopenharmony_ci    if (entry == nullptr) {
390fb299fa2Sopenharmony_ci        PKG_LOGE("Fail create gzip node for %s", pkgStream_->GetFileName().c_str());
391fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(PKG_INVALID_STATE);
392fb299fa2Sopenharmony_ci        return PKG_LZ4_FINISH;
393fb299fa2Sopenharmony_ci    }
394fb299fa2Sopenharmony_ci    ret = entry->DecodeHeader(buffer, srcOffset, srcOffset, readLen);
395fb299fa2Sopenharmony_ci    srcOffset += readLen;
396fb299fa2Sopenharmony_ci
397fb299fa2Sopenharmony_ci    // Save entry
398fb299fa2Sopenharmony_ci    pkgEntryMapId_.insert(std::pair<uint32_t, PkgEntryPtr>(entry->GetNodeId(), entry));
399fb299fa2Sopenharmony_ci    pkgEntryMapFileName_.insert(std::pair<std::string, PkgEntryPtr>(entry->GetFileName(), entry));
400fb299fa2Sopenharmony_ci    fileNames.push_back(entry->GetFileName());
401fb299fa2Sopenharmony_ci    return ret;
402fb299fa2Sopenharmony_ci}
403fb299fa2Sopenharmony_ci} // namespace Hpackage
404