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 #ifndef PKG_MANAGER_H
17 #define PKG_MANAGER_H
18 
19 #include <cstdlib>
20 #include <cstdio>
21 #include <functional>
22 #include <iostream>
23 #include <memory>
24 #include <vector>
25 #include "ring_buffer/ring_buffer.h"
26 #include "package/package.h"
27 #include "pkg_info_utils.h"
28 
29 namespace Hpackage {
30 class PkgFile;
31 class PkgStream;
32 class PkgEntry;
33 using PkgFilePtr = PkgFile *;
34 using PkgStreamPtr = PkgStream *;
35 using PkgEntryPtr = PkgEntry *;
36 
37 /**
38  * Input and output stream definition
39  */
40 class PkgStream {
41 public:
42     enum {
43         PkgStreamType_Read = 0,     // common file reading
44         PkgStreamType_Write,        // common file writing (A new file is created and the original content is deleted.)
45         PkgStreamType_MemoryMap,    // memory mapping
46         PkgStreamType_Process,      // processing while parsing
47         PkgStreamType_Buffer,       // buffer
48         PKgStreamType_FileMap,      // file map to memory
49         PkgStreamType_FlowData,     // flow data
50     };
51 
52     virtual ~PkgStream() = default;
53 
54     /**
55      * Read files.
56      *
57      * @param buff                  buffer to hold the output file content
58      * @param start                 start position of reading
59      * @param needRead              size of the data to read
60      * @param readLen               length of the read data
61      * @return                      file reading result
62      */
63     virtual int32_t Read(PkgBuffer &data, size_t start, size_t needRead, size_t &readLen) = 0;
64 
65     /**
66      * write stream
67      *
68      * @param data                  buffer to hold the output file content
69      * @param size                  size of the data to read
70      * @param start                 start position of reading
71      * @return                      file reading result
72      */
73     virtual int32_t Write(const PkgBuffer &data, size_t size, size_t start) = 0;
74 
75     virtual int32_t Flush(size_t size) = 0;
76 
77     virtual int32_t GetBuffer(PkgBuffer &buffer) const = 0;
78 
79     virtual size_t GetFileLength() = 0;
80     virtual const std::string GetFileName() const = 0;
81     virtual int32_t GetStreamType() const = 0;
82 
83     virtual void AddRef() = 0;
84     virtual void DelRef() = 0;
85     virtual bool IsRef() const = 0;
86 
87     using ExtractFileProcessor = std::function<int(const PkgBuffer &data, size_t size, size_t start,
88         bool isFinish, const void *context)>;
89 
GetBuffer(uint8_t * & buffer,size_t & size)90     int32_t GetBuffer(uint8_t *&buffer, size_t &size)
91     {
92         PkgBuffer data = {};
93         int ret = GetBuffer(data);
94         buffer = data.buffer;
95         size = data.length;
96         return ret;
97     }
98 
GetReadOffset()99     virtual size_t GetReadOffset() const
100     {
101         return 0;
102     }
103 
Stop()104     virtual void Stop()
105     {
106         return;
107     }
108 };
109 
110 class PkgFile {
111 public:
112     enum PkgType {
113         PKG_TYPE_NONE = PKG_PACK_TYPE_NONE,
114         PKG_TYPE_UPGRADE = PKG_PACK_TYPE_UPGRADE, // 升级包
115         PKG_TYPE_ZIP = PKG_PACK_TYPE_ZIP,     // zip压缩包
116         PKG_TYPE_LZ4 = PKG_PACK_TYPE_LZ4,     // lz4压缩包
117         PKG_TYPE_GZIP = PKG_PACK_TYPE_GZIP,     // gzip压缩包
118         PKG_TYPE_MAX
119     };
120 
121     using VerifyFunction = std::function<int(const PkgInfoPtr info,
122         const std::vector<uint8_t> &digest, const std::vector<uint8_t> &signature)>;
123 
124 public:
125     virtual ~PkgFile() = default;
126 
127     virtual int32_t AddEntry(const FileInfoPtr file, const PkgStreamPtr input) = 0;
128 
129     virtual int32_t SavePackage(size_t &signOffset) = 0;
130 
131     virtual int32_t ExtractFile(const PkgEntryPtr node, const PkgStreamPtr output) = 0;
132 
133     virtual int32_t LoadPackage(std::vector<std::string> &fileNames, VerifyFunction verifier = nullptr) = 0;
134 
135     virtual int32_t ParseComponents(std::vector<std::string> &fileNames) = 0;
136 
137     virtual PkgEntryPtr FindPkgEntry(const std::string &fileName) = 0;
138 
139     virtual PkgStreamPtr GetPkgStream() const = 0;
140 
141     virtual const PkgInfo *GetPkgInfo() const = 0;
142 
143     virtual PkgType GetPkgType() const = 0;
144 
145     virtual void ClearPkgStream() = 0;
146 };
147 
148 class PkgEntry {
149 public:
PkgEntry(PkgFilePtr pkgFile,uint32_t nodeId)150     PkgEntry(PkgFilePtr pkgFile, uint32_t nodeId) : nodeId_(nodeId), pkgFile_(pkgFile) {}
151 
~PkgEntry()152     virtual ~PkgEntry() {}
153 
154     virtual int32_t Init(const FileInfoPtr fileInfo, PkgStreamPtr inStream) = 0;
155 
156     virtual int32_t EncodeHeader(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen) = 0;
157 
158     virtual int32_t Pack(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen) = 0;
159 
160     virtual int32_t DecodeHeader(PkgBuffer &buffer, size_t headerOffset, size_t dataOffset,
161         size_t &decodeLen) = 0;
162 
163     virtual int32_t Unpack(PkgStreamPtr outStream) = 0;
164 
GetFileName()165     virtual const std::string GetFileName() const
166     {
167         return fileName_;
168     };
169 
170     virtual const FileInfo *GetFileInfo() const = 0;
171 
GetPkgFile()172     PkgFilePtr GetPkgFile() const
173     {
174         return pkgFile_;
175     }
176 
GetNodeId()177     uint32_t GetNodeId() const
178     {
179         return nodeId_;
180     }
181 
AddDataOffset(size_t offset)182     void AddDataOffset(size_t offset)
183     {
184         dataOffset_ += offset;
185     }
186 
187 protected:
188     int32_t Init(FileInfoPtr localFileInfo, const FileInfoPtr fileInfo,
189         PkgStreamPtr inStream);
190 
191 protected:
192     uint32_t nodeId_ {0};
193     PkgFilePtr pkgFile_ {nullptr};
194     size_t headerOffset_ {0};
195     size_t dataOffset_ {0};
196     std::string fileName_ {};
197 };
198 
199 using PkgDecodeProgress = std::function<void(int type, size_t writeDataLen, const void *context)>;
200 
201 /**
202  * Get a singleton PkgManager instance.
203  */
204 class PkgManager {
205 public:
206     using PkgManagerPtr = PkgManager *;
207     using FileInfoPtr = FileInfo *;
208     using PkgInfoPtr = PkgInfo *;
209     using StreamPtr = PkgStream *;
210     using VerifyCallback = std::function<void(int32_t result, uint32_t percent)>;
211     using PkgFileConstructor = std::function<PkgFilePtr(
212         PkgManagerPtr manager, PkgStreamPtr stream, PkgManager::PkgInfoPtr header)>;
213 
214     virtual ~PkgManager() = default;
215 
216     virtual void RegisterPkgFileCreator(const std::string &fileType, PkgFileConstructor constructor) = 0;
217 
218     static PkgManagerPtr CreatePackageInstance();
219     static PkgManagerPtr GetPackageInstance();
220     static void ReleasePackageInstance(PkgManagerPtr manager);
221 
222     /**
223      * Create an update package based on specified parameters.
224      *
225      * @param path              path of the update package
226      * @param header            header, which mainly consists of algorithm information
227      * @param files             packed file list
228      * @return                  packaging result, with the package saved as the file specified in path
229      */
230     virtual int32_t CreatePackage(const std::string &path, const std::string &keyName, PkgInfoPtr header,
231         std::vector<std::pair<std::string, ZipFileInfo>> &files) = 0;
232     virtual int32_t CreatePackage(const std::string &path, const std::string &keyName, PkgInfoPtr header,
233         std::vector<std::pair<std::string, ComponentInfo>> &files) = 0;
234     virtual int32_t CreatePackage(const std::string &path, const std::string &keyName, PkgInfoPtr header,
235         std::vector<std::pair<std::string, Lz4FileInfo>> &files) = 0;
236 
237     /**
238      * Verify the signature of the upgrade package.
239      *
240      * @param packagePath       file name of the update package
241      * @param keyPath           file name of the key used for verification
242      * @param version           version number of the update package to download
243      * @param digest            digest value
244      * @param size              digest value size
245      * @return                  verification result
246      */
247     virtual int32_t VerifyPackage(const std::string &packagePath, const std::string &keyPath,
248         const std::string &version, const PkgBuffer &digest, VerifyCallback cb) = 0;
249 
250     /**
251      * Load and parse the update package.
252      *
253      * @param packagePath       file name of the update package
254      * @param fileIds           returned file ID list
255      * @param middleTofile      file saving mode during intermediate parsing.
256      * @return                  loading and parsing result
257      */
258     virtual int32_t LoadPackage(const std::string &packagePath, const std::string &keyPath,
259         std::vector<std::string> &fileIds) = 0;
260 
261     virtual int32_t VerifyAccPackage(const std::string &packagePath, const std::string &keyPath) = 0;
262 
263     virtual int32_t VerifyOtaPackage(const std::string &devPath, uint64_t offset, size_t size) = 0;
264 
265     virtual int32_t VerifyOtaPackage(const std::string &packagePath) = 0;
266 
267     virtual int32_t VerifyBinFile(const std::string &packagePath, const std::string &keyPath,
268         const std::string &version, const PkgBuffer &digest) = 0;
269 
270     /**
271      * Get the information about the update package.
272      *
273      * @param packagePath   file name of the update package
274      * @return              information about the update package
275      */
276     virtual const PkgInfo *GetPackageInfo(const std::string &packagePath) = 0;
277 
278     /**
279      * Extract files from the update package, parse the files, and verify the hash value.
280      *
281      * @param fileId        File ID, which is obtained from the fileIds returned by the LoadPackage function
282      * @param output        output of the extracted files
283      * @return              read operation result
284      */
285     virtual int32_t ExtractFile(const std::string &fileId, StreamPtr output) = 0;
286 
287     /**
288      * Obtain information about the files in the update package.
289      *
290      * @param fileId        file ID
291      * @return              file information
292      */
293     virtual const FileInfo *GetFileInfo(const std::string &fileId) = 0;
294 
295     /**
296      * Create a a package stream to output.
297      *
298      * @param stream        stream for io management
299      * @param fileName      file name corresponding to the stream
300      * @param size          file size
301      * @param type          stream type
302      * @return              creation result; false if no access permission
303      */
304     virtual int32_t CreatePkgStream(StreamPtr &stream, const std::string &fileName, size_t size,
305         int32_t type) = 0;
306 
307     /**
308      * Create a package stream that can be processed while parsing.
309      *
310      * @param stream        stream used for io management
311      * @param fileName      file name corresponding to the stream
312      * @param processor     content processor
313      * @param context       context for the processor
314      * @return              creation result
315      */
316     virtual int32_t CreatePkgStream(StreamPtr &stream, const std::string &fileName,
317         PkgStream::ExtractFileProcessor processor, const void *context) = 0;
318 
319     /**
320      * Create a package stream that can be processed while parsing.
321      *
322      * @param stream        stream used for io management
323      * @param fileName      file name corresponding to the stream
324      * @param buffer        buffer
325      * @return              creation result
326      */
327     virtual int32_t CreatePkgStream(StreamPtr &stream, const std::string &fileName, const PkgBuffer &buffer) = 0;
328 
329     /**
330      * Create a package stream that can be processed while parsing.
331      *
332      * @param stream        stream used for io management
333      * @param fileName      file name corresponding to the stream
334      * @param buffer        ringbuffer
335      * @return              creation result
336      */
337     virtual int32_t CreatePkgStream(StreamPtr &stream, const std::string &fileName,
338         uint64_t fileLen, Updater::RingBuffer *buffer) = 0;
339 
340     /**
341      * Close the stream
342      *
343      * @param stream  stream对象
344      */
345     virtual void ClosePkgStream(StreamPtr &stream) = 0;
346 
347     virtual int32_t DecompressBuffer(FileInfoPtr info, const PkgBuffer &buffer, StreamPtr output) const = 0;
348     virtual int32_t CompressBuffer(FileInfoPtr info, const PkgBuffer &buffer, StreamPtr output) const = 0;
349 
350     virtual int32_t LoadPackageWithoutUnPack(const std::string &packagePath,
351         std::vector<std::string> &fileIds) = 0;
352 
353     virtual int32_t LoadPackageWithStream(const std::string &packagePath, const std::string &keyPath,
354         std::vector<std::string> &fileIds, uint8_t type, StreamPtr stream) = 0;
355 
356     virtual int32_t ParsePackage(StreamPtr stream, std::vector<std::string> &fileIds, int32_t type) = 0;
357 
358     virtual void SetPkgDecodeProgress(PkgDecodeProgress decodeProgress) = 0;
359 
360     virtual void PostDecodeProgress(int type, size_t writeDataLen, const void *context) = 0;
361 
362     virtual StreamPtr GetPkgFileStream(const std::string &fileName) = 0;
363 
364     virtual int32_t ParseComponents(const std::string &packagePath, std::vector<std::string> &fileName) = 0;
365 
366     /**
367      * Load and parse the update package.
368      *
369      * @param packagePath       file name of the update package
370      * @param fileIds           returned file ID list
371      * @param middleTofile      file saving mode during intermediate parsing.
372      * @return                  loading and parsing result
373      */
374     virtual int32_t LoadPackage(const std::string &packagePath,
375         std::vector<std::string> &fileIds, PkgFile::PkgType type) = 0;
376 };
377 
378 template <typename FileClassName>
NewPkgFile(PkgManager::PkgManagerPtr manager,PkgStreamPtr stream,PkgInfoPtr header)379 PkgFilePtr NewPkgFile(PkgManager::PkgManagerPtr manager, PkgStreamPtr stream, PkgInfoPtr header)
380 {
381     return new FileClassName (manager, stream, header);
382 }
383 } // namespace Hpackage
384 #endif // PKG_MANAGER_H
385