• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 using namespace std;
20 
21 namespace Hpackage {
Init(const PkgManager::FileInfoPtr fileInfo,PkgStreamPtr inStream)22 int32_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 = reinterpret_cast<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 
EncodeHeader(PkgStreamPtr inStream,size_t startOffset,size_t & encodeLen)39 int32_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 
Pack(PkgStreamPtr inStream,size_t startOffset,size_t & encodeLen)47 int32_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 
Unpack(PkgStreamPtr outStream)77 int32_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 
DecodeHeader(const PkgBuffer & buffer,size_t headerOffset,size_t dataOffset,size_t & decodeLen)109 int32_t Lz4FileEntry::DecodeHeader(const 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 
AddEntry(const PkgManager::FileInfoPtr file,const PkgStreamPtr inStream)129 int32_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 
SavePackage(size_t & offset)170 int32_t Lz4PkgFile::SavePackage(size_t &offset)
171 {
172     AddSignData(pkgInfo_.digestMethod, currentOffset_, offset);
173     return PKG_SUCCESS;
174 }
175 
LoadPackage(std::vector<std::string> & fileNames,VerifyFunction verifier)176 int32_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(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