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