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#include "pkg_manager_impl.h"
16#include <algorithm>
17#include <cctype>
18#include <cinttypes>
19#include <cstdio>
20#include <cstring>
21#include <fcntl.h>
22#include <functional>
23#include <iterator>
24#include <unistd.h>
25#include <vector>
26#include <sys/stat.h>
27#include <sys/types.h>
28#include "dump.h"
29#include "pkg_gzipfile.h"
30#include "pkg_lz4file.h"
31#include "pkg_manager.h"
32#include "pkg_upgradefile.h"
33#include "pkg_verify_util.h"
34#include "pkg_zipfile.h"
35#include "scope_guard.h"
36#include "securec.h"
37#include "updater/updater_const.h"
38#include "utils.h"
39#include "zip_pkg_parse.h"
40
41using namespace std;
42using namespace Updater;
43
44namespace Hpackage {
45constexpr int32_t BUFFER_SIZE = 4096;
46constexpr int32_t DIGEST_INFO_NO_SIGN = 0;
47constexpr int32_t DIGEST_INFO_HAS_SIGN = 1;
48constexpr int32_t DIGEST_INFO_SIGNATURE = 2;
49constexpr int32_t DIGEST_FLAGS_NO_SIGN = 1;
50constexpr int32_t DIGEST_FLAGS_HAS_SIGN = 2;
51constexpr int32_t DIGEST_FLAGS_SIGNATURE = 4;
52constexpr uint32_t VERIFY_FINSH_PERCENT = 100;
53
54PkgManager::PkgManagerPtr PkgManager::CreatePackageInstance()
55{
56    return new(std::nothrow) PkgManagerImpl();
57}
58
59void PkgManager::ReleasePackageInstance(PkgManager::PkgManagerPtr manager)
60{
61    if (manager == nullptr) {
62        return;
63    }
64    delete manager;
65    manager = nullptr;
66}
67
68PkgManagerImpl::PkgManagerImpl()
69{
70    RegisterPkgFileCreator("bin", NewPkgFile<UpgradePkgFile>);
71    RegisterPkgFileCreator("zip", NewPkgFile<ZipPkgFile>);
72    RegisterPkgFileCreator("lz4", NewPkgFile<Lz4PkgFile>);
73    RegisterPkgFileCreator("gz", NewPkgFile<GZipPkgFile>);
74}
75
76PkgManagerImpl::~PkgManagerImpl()
77{
78    ClearPkgFile();
79}
80
81void PkgManagerImpl::ClearPkgFile()
82{
83    auto iter = pkgFiles_.begin();
84    while (iter != pkgFiles_.end()) {
85        PkgFilePtr file = (*iter);
86        delete file;
87        file = nullptr;
88        iter = pkgFiles_.erase(iter);
89    }
90    std::lock_guard<std::mutex> lock(mapLock_);
91    auto iter1 = pkgStreams_.begin();
92    while (iter1 != pkgStreams_.end()) {
93        PkgStreamPtr stream = (*iter1).second;
94        delete stream;
95        stream = nullptr;
96        iter1 = pkgStreams_.erase(iter1);
97    }
98}
99
100int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string &keyName, PkgInfoPtr header,
101    std::vector<std::pair<std::string, ZipFileInfo>> &files)
102{
103    int32_t ret = SetSignVerifyKeyName(keyName);
104    if (ret != PKG_SUCCESS) {
105        PKG_LOGE("ZipFileInfo Invalid keyname");
106        return ret;
107    }
108    if (files.size() <= 0 || header == nullptr) {
109        PKG_LOGE("ZipFileInfo Invalid param");
110        return PKG_INVALID_PARAM;
111    }
112    size_t offset = 0;
113    PkgFilePtr pkgFile = CreatePackage<ZipFileInfo>(path, header, files, offset);
114    if (pkgFile == nullptr) {
115        return PKG_INVALID_FILE;
116    }
117    delete pkgFile;
118    pkgFile = nullptr;
119    return ret;
120}
121
122int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string &keyName, PkgInfoPtr header,
123    std::vector<std::pair<std::string, ComponentInfo>> &files)
124{
125    int32_t ret = SetSignVerifyKeyName(keyName);
126    if (ret != PKG_SUCCESS) {
127        PKG_LOGE("ComponentInfo Invalid keyname");
128        return ret;
129    }
130    if (files.size() <= 0 || header == nullptr) {
131        PKG_LOGE("ComponentInfo sssInvalid param");
132        return PKG_INVALID_PARAM;
133    }
134    size_t offset = 0;
135    PkgFilePtr pkgFile = CreatePackage<ComponentInfo>(path, header, files, offset);
136    if (pkgFile == nullptr) {
137        return PKG_INVALID_FILE;
138    }
139    ret = Sign(pkgFile->GetPkgStream(), offset, header);
140    delete pkgFile;
141    pkgFile = nullptr;
142    return ret;
143}
144
145int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string &keyName, PkgInfoPtr header,
146    std::vector<std::pair<std::string, Lz4FileInfo>> &files)
147{
148    int32_t ret = SetSignVerifyKeyName(keyName);
149    if (ret != PKG_SUCCESS) {
150        PKG_LOGE("Invalid keyname");
151        return ret;
152    }
153    if (files.size() != 1 || header == nullptr) {
154        PKG_LOGE("Invalid param");
155        return PKG_INVALID_PARAM;
156    }
157    size_t offset = 0;
158    PkgFilePtr pkgFile = CreatePackage<Lz4FileInfo>(path, header, files, offset);
159    if (pkgFile == nullptr) {
160        return PKG_INVALID_FILE;
161    }
162    ret = Sign(pkgFile->GetPkgStream(), offset, header);
163    delete pkgFile;
164    pkgFile = nullptr;
165    return ret;
166}
167
168template<class T>
169PkgFilePtr PkgManagerImpl::CreatePackage(const std::string &path, PkgInfoPtr header,
170    std::vector<std::pair<std::string, T>> &files, size_t &offset)
171{
172    PkgStreamPtr stream = nullptr;
173    int32_t ret = CreatePkgStream(stream, path, 0, PkgStream::PkgStreamType_Write);
174    if (ret != PKG_SUCCESS) {
175        PKG_LOGE("CreatePackage fail %s", path.c_str());
176        return nullptr;
177    }
178
179    PkgFilePtr pkgFile = CreatePackage(PkgStreamImpl::ConvertPkgStream(stream),
180        static_cast<PkgFile::PkgType>(header->pkgType), header);
181    if (pkgFile == nullptr) {
182        PKG_LOGE("CreatePackage fail %s", path.c_str());
183        ClosePkgStream(stream);
184        return nullptr;
185    }
186
187    PkgStreamPtr inputStream = nullptr;
188    for (size_t i = 0; i < files.size(); i++) {
189        ret = CreatePkgStream(inputStream, files[i].first, 0, PkgStream::PkgStreamType_Read);
190        if (ret != PKG_SUCCESS) {
191            PKG_LOGE("Create stream fail %s", files[i].first.c_str());
192            break;
193        }
194        ret = pkgFile->AddEntry(reinterpret_cast<const FileInfoPtr>(&(files[i].second)), inputStream);
195        if (ret != PKG_SUCCESS) {
196            PKG_LOGE("Add entry fail %s", files[i].first.c_str());
197            break;
198        }
199        ClosePkgStream(inputStream);
200        inputStream = nullptr;
201    }
202    if (ret != PKG_SUCCESS) {
203        ClosePkgStream(inputStream);
204        delete pkgFile;
205        pkgFile = nullptr;
206        return nullptr;
207    }
208    ret = pkgFile->SavePackage(offset);
209    if (ret != PKG_SUCCESS) {
210        delete pkgFile;
211        pkgFile = nullptr;
212        return nullptr;
213    }
214    return pkgFile;
215}
216
217void PkgManagerImpl::RegisterPkgFileCreator(const std::string &fileType, PkgFileConstructor constructor)
218{
219    if (!pkgFileCreator_.emplace(fileType, constructor).second) {
220        LOG(ERROR) << "emplace: " << fileType << " fail";
221    }
222}
223
224PkgFilePtr PkgManagerImpl::CreatePackage(PkgStreamPtr stream, PkgFile::PkgType type, PkgInfoPtr header)
225{
226    UNUSED(type);
227    PkgFilePtr pkgFile = nullptr;
228    std::string pkgName = stream->GetFileName();
229    std::string pkgType = GetPkgName(pkgName);
230    auto iter = pkgFileCreator_.find(pkgType);
231    if (iter == pkgFileCreator_.end()) {
232        LOG(ERROR) << "fileType is not registered: " << pkgType;
233        return pkgFile;
234    }
235    pkgFile = iter->second(this, stream, header);
236    return pkgFile;
237}
238
239int32_t PkgManagerImpl::LoadPackageWithoutUnPack(const std::string &packagePath,
240    std::vector<std::string> &fileIds)
241{
242    PkgFile::PkgType pkgType = GetPkgTypeByName(packagePath);
243    int32_t ret = LoadPackage(packagePath, fileIds, pkgType);
244    if (ret != PKG_SUCCESS) {
245        PKG_LOGE("Parse %s fail ", packagePath.c_str());
246        ClearPkgFile();
247        return ret;
248    }
249    return PKG_SUCCESS;
250}
251
252int32_t PkgManagerImpl::ParsePackage(StreamPtr stream, std::vector<std::string> &fileIds, int32_t type)
253{
254    if (stream == nullptr) {
255        PKG_LOGE("Invalid stream");
256        return PKG_INVALID_PARAM;
257    }
258    PkgFilePtr pkgFile = CreatePackage(static_cast<PkgStreamPtr>(stream), static_cast<PkgFile::PkgType>(type), nullptr);
259    if (pkgFile == nullptr) {
260        PKG_LOGE("Create package fail %s", stream->GetFileName().c_str());
261        return PKG_INVALID_PARAM;
262    }
263
264    int32_t ret = pkgFile->LoadPackage(fileIds,
265        [](const PkgInfoPtr info, const std::vector<uint8_t> &digest, const std::vector<uint8_t> &signature)->int {
266            return PKG_SUCCESS;
267        });
268    if (ret != PKG_SUCCESS) {
269        PKG_LOGE("Load package fail %s", stream->GetFileName().c_str());
270        pkgFile->ClearPkgStream();
271        delete pkgFile;
272        return ret;
273    }
274    pkgFiles_.push_back(pkgFile);
275    return PKG_SUCCESS;
276}
277
278int32_t PkgManagerImpl::LoadPackage(const std::string &packagePath, const std::string &keyPath,
279    std::vector<std::string> &fileIds)
280{
281    if (access(packagePath.c_str(), 0) != 0) {
282        UPDATER_LAST_WORD(PKG_INVALID_FILE);
283        return PKG_INVALID_FILE;
284    }
285    if (SetSignVerifyKeyName(keyPath) != PKG_SUCCESS) {
286        UPDATER_LAST_WORD(PKG_INVALID_FILE);
287        return PKG_INVALID_FILE;
288    }
289    // Check if package already loaded
290    for (auto iter : pkgFiles_) {
291        if (iter != nullptr && iter->GetPkgStream()->GetFileName().compare(packagePath) == 0) {
292            return PKG_SUCCESS;
293        }
294    }
295    PkgFile::PkgType pkgType = GetPkgTypeByName(packagePath);
296    unzipToFile_ = ((pkgType == PkgFile::PKG_TYPE_GZIP) ? true : unzipToFile_);
297    if (pkgType == PkgFile::PKG_TYPE_UPGRADE) {
298        int32_t ret = LoadPackage(packagePath, fileIds, pkgType);
299        if (ret != PKG_SUCCESS) {
300            ClearPkgFile();
301            UPDATER_LAST_WORD(ret);
302            PKG_LOGE("Parse %s fail ", packagePath.c_str());
303            return ret;
304        }
305    } else if (pkgType != PkgFile::PKG_TYPE_NONE) {
306        std::vector<std::string> innerFileNames;
307        int32_t ret = LoadPackage(packagePath, innerFileNames, pkgType);
308        if (ret != PKG_SUCCESS) {
309            ClearPkgFile();
310            PKG_LOGE("Unzip %s fail ", packagePath.c_str());
311            return ret;
312        }
313        for (auto name : innerFileNames) {
314            pkgType = GetPkgTypeByName(name);
315            if (pkgType == PkgFile::PKG_TYPE_NONE || (pkgType == PkgFile::PKG_TYPE_UPGRADE
316                && std::find(innerFileNames.begin(), innerFileNames.end(), "board_list") != innerFileNames.end())) {
317                fileIds.push_back(name);
318                continue;
319            }
320            ret = ExtraAndLoadPackage(GetFilePath(packagePath), name, pkgType, fileIds);
321            if (ret != PKG_SUCCESS) {
322                ClearPkgFile();
323                UPDATER_LAST_WORD(ret);
324                PKG_LOGE("unpack %s fail in package %s ", name.c_str(), packagePath.c_str());
325                return ret;
326            }
327        }
328    }
329    return PKG_SUCCESS;
330}
331
332const std::string PkgManagerImpl::GetExtraPath(const std::string &path)
333{
334    if (path.find(Updater::SDCARD_CARD_PATH) != string::npos) {
335        return path;
336    } else if (path == UPDATRE_SCRIPT_ZIP) {
337        return "/tmp/";
338    }
339
340    return string(Updater::UPDATER_PATH) + "/";
341}
342
343int32_t PkgManagerImpl::ExtraAndLoadPackage(const std::string &path, const std::string &name,
344    PkgFile::PkgType type, std::vector<std::string> &fileIds)
345{
346    int32_t ret = PKG_SUCCESS;
347    const FileInfo *info = GetFileInfo(name);
348    if (info == nullptr) {
349        PKG_LOGE("Create middle stream fail %s", name.c_str());
350        return PKG_INVALID_FILE;
351    }
352
353    PkgStreamPtr stream = nullptr;
354    struct stat st {};
355    const std::string tempPath = GetExtraPath(path);
356    if (stat(tempPath.c_str(), &st) != 0) {
357#ifndef __WIN32
358        (void)mkdir(tempPath.c_str(), 0775); // 0775 : rwxrwxr-x
359#endif
360    }
361
362    // Extract package to file or memory
363    if (unzipToFile_ || type == PkgFile::PKG_TYPE_UPGRADE) {
364        ret = CreatePkgStream(stream, tempPath + name + ".tmp", info->unpackedSize, PkgStream::PkgStreamType_Write);
365    } else {
366        ret = CreatePkgStream(stream, tempPath + name + ".tmp", info->unpackedSize, PkgStream::PkgStreamType_MemoryMap);
367    }
368    if (ret != PKG_SUCCESS) {
369        PKG_LOGE("Create middle stream fail %s", name.c_str());
370        return ret;
371    }
372
373    ret = ExtractFile(name, stream);
374    if (ret != PKG_SUCCESS) {
375        PKG_LOGE("Extract file fail %s", name.c_str());
376        ClosePkgStream(stream);
377        return ret;
378    }
379    return LoadPackageWithStream(path, fileIds, type, stream);
380}
381
382int32_t PkgManagerImpl::LoadPackage(const std::string &packagePath, std::vector<std::string> &fileIds,
383    PkgFile::PkgType type)
384{
385    PkgStreamPtr stream = nullptr;
386    int32_t ret = CreatePkgStream(stream, packagePath, 0, PkgStream::PKgStreamType_FileMap);
387    if (ret != PKG_SUCCESS) {
388        PKG_LOGE("Create input stream fail %s", packagePath.c_str());
389        UPDATER_LAST_WORD(ret);
390        return ret;
391    }
392    return LoadPackageWithStream(packagePath, fileIds, type, stream);
393}
394
395int32_t PkgManagerImpl::LoadPackageWithStream(const std::string &packagePath, const std::string &keyPath,
396    std::vector<std::string> &fileIds, uint8_t type, StreamPtr stream)
397{
398    int32_t ret = SetSignVerifyKeyName(keyPath);
399    if (ret != PKG_SUCCESS) {
400        PKG_LOGE("Invalid keyname");
401        return ret;
402    }
403
404    return LoadPackageWithStream(packagePath, fileIds, static_cast<PkgFile::PkgType>(type),
405        static_cast<PkgStreamPtr>(stream));
406}
407
408int32_t PkgManagerImpl::LoadPackageWithStream(const std::string &packagePath,
409    std::vector<std::string> &fileIds, PkgFile::PkgType type, PkgStreamPtr stream)
410{
411    int32_t ret = PKG_SUCCESS;
412    PkgFilePtr pkgFile = CreatePackage(stream, type, nullptr);
413    if (pkgFile == nullptr) {
414        PKG_LOGE("Create package fail %s", packagePath.c_str());
415        ClosePkgStream(stream);
416        UPDATER_LAST_WORD(ret);
417        return PKG_INVALID_PARAM;
418    }
419
420    ret = pkgFile->LoadPackage(fileIds,
421        [this](const PkgInfoPtr info, const std::vector<uint8_t> &digest, const std::vector<uint8_t> &signature)->int {
422            return Verify(info->digestMethod, digest, signature);
423        });
424    if (ret != PKG_SUCCESS) {
425        PKG_LOGE("Load package fail %s", packagePath.c_str());
426        delete pkgFile;
427        UPDATER_LAST_WORD(ret);
428        return ret;
429    }
430    pkgFiles_.push_back(pkgFile);
431    return PKG_SUCCESS;
432}
433
434int32_t PkgManagerImpl::ExtractFile(const std::string &path, PkgManager::StreamPtr output)
435{
436    if (output == nullptr) {
437        PKG_LOGE("Invalid stream");
438        UPDATER_LAST_WORD(PKG_INVALID_STREAM);
439        return PKG_INVALID_STREAM;
440    }
441    int32_t ret = PKG_INVALID_FILE;
442    PkgEntryPtr pkgEntry = GetPkgEntry(path);
443    if (pkgEntry != nullptr && pkgEntry->GetPkgFile() != nullptr) {
444        ret = pkgEntry->GetPkgFile()->ExtractFile(pkgEntry, PkgStreamImpl::ConvertPkgStream(output));
445    } else {
446        PKG_LOGE("Can not find file %s", path.c_str());
447    }
448    return ret;
449}
450
451int32_t PkgManagerImpl::ParseComponents(const std::string &packagePath, std::vector<std::string> &fileName)
452{
453    int32_t ret = PKG_INVALID_FILE;
454    for (auto iter : pkgFiles_) {
455        PkgFilePtr pkgFile = iter;
456        if (pkgFile != nullptr && pkgFile->GetPkgType() == PkgFile::PKG_TYPE_UPGRADE) {
457            return pkgFile->ParseComponents(fileName);
458        }
459    }
460    return ret;
461}
462
463const PkgInfo *PkgManagerImpl::GetPackageInfo(const std::string &packagePath)
464{
465    for (auto iter : pkgFiles_) {
466        PkgFilePtr pkgFile = iter;
467        if (pkgFile != nullptr && pkgFile->GetPkgType() == PkgFile::PKG_TYPE_UPGRADE) {
468            return pkgFile->GetPkgInfo();
469        }
470    }
471    return nullptr;
472}
473
474const FileInfo *PkgManagerImpl::GetFileInfo(const std::string &path)
475{
476    PkgEntryPtr pkgEntry = GetPkgEntry(path);
477    if (pkgEntry != nullptr) {
478        return pkgEntry->GetFileInfo();
479    }
480    return nullptr;
481}
482
483PkgEntryPtr PkgManagerImpl::GetPkgEntry(const std::string &path)
484{
485    // Find out pkgEntry by fileId.
486    for (auto iter : pkgFiles_) {
487        PkgFilePtr pkgFile = iter;
488        PkgEntryPtr pkgEntry = pkgFile->FindPkgEntry(path);
489        if (pkgEntry == nullptr) {
490            continue;
491        }
492        return pkgEntry;
493    }
494    return nullptr;
495}
496
497PkgManager::StreamPtr PkgManagerImpl::GetPkgFileStream(const std::string &fileName)
498{
499    auto iter = pkgStreams_.find(fileName);
500    if (iter != pkgStreams_.end()) {
501        return (*iter).second;
502    }
503
504    return nullptr;
505}
506
507int32_t PkgManagerImpl::CreatePkgStream(StreamPtr &stream, const std::string &fileName, const PkgBuffer &buffer)
508{
509    PkgStreamPtr pkgStream = new MemoryMapStream(this, fileName, buffer, PkgStream::PkgStreamType_Buffer);
510    if (pkgStream == nullptr) {
511        PKG_LOGE("Failed to create stream");
512        return -1;
513    }
514    stream = pkgStream;
515    return PKG_SUCCESS;
516}
517
518int32_t PkgManagerImpl::CreatePkgStream(StreamPtr &stream, const std::string &fileName,
519    uint64_t fileLen, RingBuffer *buffer)
520{
521    PkgStreamPtr pkgStream = new(std::nothrow) FlowDataStream(this, fileName, fileLen,
522        buffer, PkgStream::PkgStreamType_FlowData);
523    if (pkgStream == nullptr) {
524        PKG_LOGE("Failed to create stream");
525        return -1;
526    }
527    stream = pkgStream;
528    return PKG_SUCCESS;
529}
530
531int32_t PkgManagerImpl::DoCreatePkgStream(PkgStreamPtr &stream, const std::string &fileName, int32_t type)
532{
533    static char const *modeFlags[] = { "rb", "wb+" };
534    char realPath[PATH_MAX + 1] = {};
535#ifdef _WIN32
536    if (type == PkgStream::PkgStreamType_Read && _fullpath(realPath, fileName.c_str(), PATH_MAX) == nullptr) {
537#else
538    if (type == PkgStream::PkgStreamType_Read && realpath(fileName.c_str(), realPath) == nullptr) {
539#endif
540        UPDATER_LAST_WORD(PKG_INVALID_FILE);
541        return PKG_INVALID_FILE;
542    }
543    if (CheckFile(fileName, type) != PKG_SUCCESS) {
544        UPDATER_LAST_WORD(PKG_INVALID_FILE);
545        PKG_LOGE("Fail to check file %s ", fileName.c_str());
546        return PKG_INVALID_FILE;
547    }
548    std::lock_guard<std::mutex> lock(mapLock_);
549    if (pkgStreams_.find(fileName) != pkgStreams_.end()) {
550        PkgStreamPtr mapStream = pkgStreams_[fileName];
551        mapStream->AddRef();
552        stream = mapStream;
553        return PKG_SUCCESS;
554    }
555    FILE *file = nullptr;
556    if (type == PkgStream::PkgStreamType_Read) {
557        file = fopen(realPath, modeFlags[type]);
558    } else {
559        file = fopen(fileName.c_str(), modeFlags[type]);
560    }
561    if (file == nullptr) {
562        UPDATER_LAST_WORD(PKG_INVALID_FILE);
563        PKG_LOGE("Fail to open file %s ", fileName.c_str());
564        return PKG_INVALID_FILE;
565    }
566    stream = new FileStream(this, fileName, file, type);
567    return PKG_SUCCESS;
568}
569
570int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string &fileName, size_t size, int32_t type)
571{
572    Updater::UPDATER_INIT_RECORD;
573    stream = nullptr;
574    if (type == PkgStream::PkgStreamType_Write || type == PkgStream::PkgStreamType_Read) {
575        int32_t ret = DoCreatePkgStream(stream, fileName, type);
576        if (ret != PKG_SUCCESS) {
577            UPDATER_LAST_WORD(ret);
578            return ret;
579        }
580    } else if (type == PkgStream::PkgStreamType_MemoryMap || type == PkgStream::PKgStreamType_FileMap) {
581        if ((size == 0) && (access(fileName.c_str(), 0) != 0)) {
582            UPDATER_LAST_WORD(PKG_INVALID_FILE);
583            return PKG_INVALID_FILE;
584        }
585        size_t fileSize = (size == 0) ? GetFileSize(fileName) : size;
586        if (fileSize <= 0) {
587            UPDATER_LAST_WORD(PKG_INVALID_FILE);
588            PKG_LOGE("Fail to check file size %s ", fileName.c_str());
589            return PKG_INVALID_FILE;
590        }
591        uint8_t *memoryMap = nullptr;
592        if (type == PkgStream::PkgStreamType_MemoryMap) {
593            memoryMap = AnonymousMap(fileName, fileSize);
594        } else {
595            memoryMap = FileMap(fileName);
596        }
597        if (memoryMap == nullptr) {
598            UPDATER_LAST_WORD(PKG_INVALID_FILE);
599            PKG_LOGE("Fail to map memory %s ", fileName.c_str());
600            return PKG_INVALID_FILE;
601        }
602        PkgBuffer buffer(memoryMap, fileSize);
603        stream = new MemoryMapStream(this, fileName, buffer);
604    } else {
605        UPDATER_LAST_WORD(-1);
606        return -1;
607    }
608    std::lock_guard<std::mutex> lock(mapLock_);
609    pkgStreams_[fileName] = stream;
610    return PKG_SUCCESS;
611}
612
613int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string &fileName,
614    PkgStream::ExtractFileProcessor processor, const void *context)
615{
616    stream = new ProcessorStream(this, fileName, processor, context);
617    if (stream == nullptr) {
618        PKG_LOGE("Failed to create stream");
619        return -1;
620    }
621    return PKG_SUCCESS;
622}
623
624void PkgManagerImpl::ClosePkgStream(PkgStreamPtr &stream)
625{
626    PkgStreamPtr mapStream = stream;
627    if (mapStream == nullptr) {
628        return;
629    }
630
631    std::lock_guard<std::mutex> lock(mapLock_);
632    auto iter = pkgStreams_.find(mapStream->GetFileName());
633    if (iter != pkgStreams_.end()) {
634        mapStream->DelRef();
635        if (mapStream->IsRef()) {
636            return;
637        }
638        pkgStreams_.erase(iter);
639    }
640    delete mapStream;
641    stream = nullptr;
642}
643
644std::string PkgManagerImpl::GetPkgName(const std::string &path)
645{
646    std::size_t pos = path.find_last_of('.');
647    if (pos == std::string::npos || pos < 1) {
648        return "";
649    }
650    std::string pkgName = path.substr(pos + 1, -1);
651    std::transform(pkgName.begin(), pkgName.end(), pkgName.begin(), ::tolower);
652    if (pkgName.compare("tmp") != 0) {
653        return pkgName;
654    }
655    std::size_t secPos = path.find_last_of('.', pos - 1);
656    if (secPos == std::string::npos) {
657        return "";
658    }
659    std::string secPkgName = path.substr(secPos + 1, pos - secPos - 1);
660    std::transform(secPkgName.begin(), secPkgName.end(), secPkgName.begin(), ::tolower);
661    return secPkgName;
662}
663
664PkgFile::PkgType PkgManagerImpl::GetPkgTypeByName(const std::string &path)
665{
666    std::size_t pos = path.find_last_of('.');
667    if (pos == std::string::npos) {
668        return PkgFile::PKG_TYPE_NONE;
669    }
670    std::string postfix = path.substr(pos + 1, -1);
671    std::transform(postfix.begin(), postfix.end(), postfix.begin(), ::tolower);
672
673    if (path.compare("update.bin") == 0) {
674        return PkgFile::PKG_TYPE_UPGRADE;
675    } else if (path.substr(pos + 1, -1).compare("zip") == 0) {
676        return PkgFile::PKG_TYPE_ZIP;
677    } else if (path.substr(pos + 1, -1).compare("lz4") == 0) {
678        return PkgFile::PKG_TYPE_LZ4;
679    } else if (path.substr(pos + 1, -1).compare("gz") == 0) {
680        return PkgFile::PKG_TYPE_GZIP;
681    }
682    return PkgFile::PKG_TYPE_NONE;
683}
684
685int32_t PkgManagerImpl::VerifyPackage(const std::string &packagePath, const std::string &keyPath,
686    const std::string &version, const PkgBuffer &digest, VerifyCallback cb)
687{
688    int32_t ret = SetSignVerifyKeyName(keyPath);
689    if (ret != PKG_SUCCESS) {
690        PKG_LOGE("Invalid keyname");
691        return ret;
692    }
693
694    PkgFile::PkgType type = GetPkgTypeByName(packagePath);
695    if (type != PkgFile::PKG_TYPE_UPGRADE) {
696        ret = VerifyOtaPackage(packagePath);
697    } else if (digest.buffer != nullptr) {
698        ret = VerifyBinFile(packagePath, keyPath, version, digest);
699    } else {
700        PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance();
701        if (pkgManager == nullptr) {
702            PKG_LOGE("pkgManager is nullptr");
703            return PKG_INVALID_SIGNATURE;
704        }
705        std::vector<std::string> components;
706        ret = pkgManager->LoadPackage(packagePath, keyPath, components);
707        PkgManager::ReleasePackageInstance(pkgManager);
708    }
709    cb(ret, VERIFY_FINSH_PERCENT);
710    if (ret != PKG_SUCCESS) {
711        PKG_LOGE("Verify file %s fail", packagePath.c_str());
712        return ret;
713    }
714    PKG_LOGI("Verify file %s success", packagePath.c_str());
715    return ret;
716}
717
718int32_t PkgManagerImpl::DoGenerateFileDigest(PkgStreamPtr stream, uint8_t flags, const size_t fileLen,
719    PkgBuffer &buff, std::pair<DigestAlgorithm::DigestAlgorithmPtr, DigestAlgorithm::DigestAlgorithmPtr> &algorithm)
720{
721    size_t offset = 0;
722    size_t readLen = 0;
723    size_t needReadLen = fileLen;
724    size_t buffSize = BUFFER_SIZE;
725    if (flags & DIGEST_FLAGS_SIGNATURE) {
726        if (SIGN_TOTAL_LEN >= fileLen) {
727            return PKG_INVALID_SIGNATURE;
728        }
729        needReadLen = fileLen - SIGN_TOTAL_LEN;
730    }
731    while (offset < needReadLen) {
732        if ((needReadLen - offset) < buffSize) {
733            buffSize = needReadLen - offset;
734        }
735        int32_t ret = stream->Read(buff, offset, buffSize, readLen);
736        if (ret != PKG_SUCCESS) {
737            PKG_LOGE("read buffer fail %s", stream->GetFileName().c_str());
738            return ret;
739        }
740        if (flags & DIGEST_FLAGS_HAS_SIGN) {
741            algorithm.first->Update(buff, readLen);
742        }
743        if (flags & DIGEST_FLAGS_NO_SIGN) {
744            algorithm.second->Update(buff, readLen);
745        }
746        offset += readLen;
747        PostDecodeProgress(POST_TYPE_VERIFY_PKG, readLen, nullptr);
748        readLen = 0;
749    }
750
751    // Read last signatureLen
752    if (flags & DIGEST_FLAGS_SIGNATURE) {
753        readLen = 0;
754        int32_t ret = stream->Read(buff, offset, SIGN_TOTAL_LEN, readLen);
755        if (ret != PKG_SUCCESS) {
756            PKG_LOGE("read buffer failed %s", stream->GetFileName().c_str());
757            return ret;
758        }
759        if (flags & DIGEST_FLAGS_HAS_SIGN) {
760            algorithm.first->Update(buff, readLen);
761        }
762        PkgBuffer data(SIGN_TOTAL_LEN);
763        if (flags & DIGEST_FLAGS_NO_SIGN) {
764            algorithm.second->Update(data, SIGN_TOTAL_LEN);
765        }
766    }
767    return PKG_SUCCESS;
768}
769
770int32_t PkgManagerImpl::GenerateFileDigest(PkgStreamPtr stream,
771    uint8_t digestMethod, uint8_t flags, std::vector<std::vector<uint8_t>> &digestInfos, size_t hashBufferLen)
772{
773    size_t fileLen = (hashBufferLen == 0) ? stream->GetFileLength() : hashBufferLen;
774    size_t digestLen = DigestAlgorithm::GetDigestLen(digestMethod);
775    size_t signatureLen = DigestAlgorithm::GetSignatureLen(digestMethod);
776    // Check entire package
777    DigestAlgorithm::DigestAlgorithmPtr algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(digestMethod);
778    if (algorithm == nullptr) {
779        PKG_LOGE("Invalid file %s", stream->GetFileName().c_str());
780        return PKG_NOT_EXIST_ALGORITHM;
781    }
782    algorithm->Init();
783    // Get verify algorithm
784    DigestAlgorithm::DigestAlgorithmPtr algorithmInner = PkgAlgorithmFactory::GetDigestAlgorithm(digestMethod);
785    if (algorithmInner == nullptr) {
786        PKG_LOGE("Invalid file %s", stream->GetFileName().c_str());
787        return PKG_NOT_EXIST_ALGORITHM;
788    }
789    algorithmInner->Init();
790    PkgBuffer buff(BUFFER_SIZE);
791    std::pair<DigestAlgorithm::DigestAlgorithmPtr, DigestAlgorithm::DigestAlgorithmPtr> digestAlgorithm(
792        algorithm, algorithmInner);
793    int32_t ret = DoGenerateFileDigest(stream, flags, fileLen, buff, digestAlgorithm);
794    if (ret != PKG_SUCCESS) {
795        return ret;
796    }
797    if (flags & DIGEST_FLAGS_HAS_SIGN) {
798        PkgBuffer result(digestInfos[DIGEST_INFO_HAS_SIGN].data(), digestLen);
799        algorithm->Final(result);
800    }
801    if (flags & DIGEST_FLAGS_NO_SIGN) {
802        PkgBuffer result(digestInfos[DIGEST_INFO_NO_SIGN].data(), digestLen);
803        algorithmInner->Final(result);
804    }
805
806    if (flags & DIGEST_FLAGS_SIGNATURE) {
807        uint8_t *buffer = buff.buffer;
808        if (digestMethod != PKG_DIGEST_TYPE_SHA256) {
809            buffer = buff.buffer + SIGN_SHA256_LEN;
810        }
811        if (memcpy_s(digestInfos[DIGEST_INFO_SIGNATURE].data(), signatureLen, buffer, signatureLen) != EOK) {
812            PKG_LOGE("GenerateFileDigest memcpy failed");
813            return PKG_NONE_MEMORY;
814        }
815    }
816    return PKG_SUCCESS;
817}
818
819int32_t PkgManagerImpl::Verify(uint8_t digestMethod, const std::vector<uint8_t> &digest,
820    const std::vector<uint8_t> &signature)
821{
822    SignAlgorithm::SignAlgorithmPtr signAlgorithm = PkgAlgorithmFactory::GetVerifyAlgorithm(
823        signVerifyKeyName_, digestMethod);
824    if (signAlgorithm == nullptr) {
825        PKG_LOGE("Invalid sign algo");
826        return PKG_INVALID_SIGNATURE;
827    }
828    return signAlgorithm->VerifyDigest(digest, signature);
829}
830
831int32_t PkgManagerImpl::Sign(PkgStreamPtr stream, size_t offset, const PkgInfoPtr &info)
832{
833    if (info == nullptr) {
834        PKG_LOGE("Invalid param");
835        return PKG_INVALID_PARAM;
836    }
837    if (info->signMethod == PKG_SIGN_METHOD_NONE) {
838        return PKG_SUCCESS;
839    }
840
841    size_t digestLen = DigestAlgorithm::GetDigestLen(info->digestMethod);
842    std::vector<std::vector<uint8_t>> digestInfos(DIGEST_INFO_SIGNATURE + 1);
843    digestInfos[DIGEST_INFO_HAS_SIGN].resize(digestLen);
844    int32_t ret = GenerateFileDigest(stream, info->digestMethod, DIGEST_FLAGS_HAS_SIGN, digestInfos);
845    if (ret != PKG_SUCCESS) {
846        PKG_LOGE("Fail to generate signature %s", stream->GetFileName().c_str());
847        return ret;
848    }
849    SignAlgorithm::SignAlgorithmPtr signAlgorithm =
850        PkgAlgorithmFactory::GetSignAlgorithm(signVerifyKeyName_, info->signMethod, info->digestMethod);
851    if (signAlgorithm == nullptr) {
852        PKG_LOGE("Invalid sign algo");
853        return PKG_INVALID_SIGNATURE;
854    }
855    size_t signLen = DigestAlgorithm::GetSignatureLen(info->digestMethod);
856    std::vector<uint8_t> signedData(signLen, 0);
857    // Clear buffer
858    PkgBuffer signBuffer(signedData);
859    ret = stream->Write(signBuffer, signLen, offset);
860    size_t signDataLen = 0;
861    signedData.clear();
862    PkgBuffer digest(digestInfos[DIGEST_INFO_HAS_SIGN].data(), digestLen);
863    ret = signAlgorithm->SignBuffer(digest, signedData, signDataLen);
864    if (ret != PKG_SUCCESS) {
865        PKG_LOGE("Fail to SignBuffer %s", stream->GetFileName().c_str());
866        return ret;
867    }
868    if (signDataLen > signLen) {
869        PKG_LOGE("SignData len %zu more %zu", signDataLen, signLen);
870        return PKG_INVALID_SIGNATURE;
871    }
872    PKG_LOGI("Signature %zu %zu %s", offset, signDataLen, stream->GetFileName().c_str());
873    ret = stream->Write(signBuffer, signDataLen, offset);
874    stream->Flush(offset + signedData.size());
875    if (ret != PKG_SUCCESS) {
876        PKG_LOGE("Fail to Write signature %s", stream->GetFileName().c_str());
877        return ret;
878    }
879    PKG_LOGW("Sign file %s success", stream->GetFileName().c_str());
880    return ret;
881}
882
883int32_t PkgManagerImpl::SetSignVerifyKeyName(const std::string &keyName)
884{
885    Updater::UPDATER_INIT_RECORD;
886    if (keyName == Updater::Utils::ON_SERVER) {
887        return PKG_SUCCESS;
888    }
889    if (access(keyName.c_str(), 0) != 0) {
890        UPDATER_LAST_WORD(PKG_INVALID_FILE);
891        PKG_LOGE("Invalid keyname");
892        return PKG_INVALID_FILE;
893    }
894    signVerifyKeyName_ = keyName;
895    return PKG_SUCCESS;
896}
897
898int32_t PkgManagerImpl::DecompressBuffer(FileInfoPtr info, const PkgBuffer &buffer, StreamPtr stream) const
899{
900    if (info == nullptr || buffer.buffer == nullptr || stream == nullptr) {
901        PKG_LOGE("DecompressBuffer Param is null");
902        return PKG_INVALID_PARAM;
903    }
904    PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(info);
905    if (algorithm == nullptr) {
906        PKG_LOGE("DecompressBuffer Can not get algorithm for %s", info->identity.c_str());
907        return PKG_INVALID_PARAM;
908    }
909
910    std::shared_ptr<MemoryMapStream> inStream = std::make_shared<MemoryMapStream>(
911        (PkgManager::PkgManagerPtr)this, info->identity, buffer, PkgStream::PkgStreamType_Buffer);
912    if (inStream == nullptr) {
913        PKG_LOGE("DecompressBuffer Can not create stream for %s", info->identity.c_str());
914        return PKG_INVALID_PARAM;
915    }
916    PkgAlgorithmContext context = {{0, 0}, {buffer.length, 0}, 0, info->digestMethod};
917    int32_t ret = algorithm->Unpack(inStream.get(), PkgStreamImpl::ConvertPkgStream(stream), context);
918    if (ret != PKG_SUCCESS) {
919        PKG_LOGE("Fail Decompress for %s", info->identity.c_str());
920        return ret;
921    }
922    PKG_LOGI("packedSize: %zu unpackedSize: %zu ", buffer.length, context.unpackedSize);
923    PkgStreamImpl::ConvertPkgStream(stream)->Flush(context.unpackedSize);
924    info->packedSize = context.packedSize;
925    info->unpackedSize = context.unpackedSize;
926    algorithm->UpdateFileInfo(info);
927    return PKG_SUCCESS;
928}
929
930int32_t PkgManagerImpl::CompressBuffer(FileInfoPtr info, const PkgBuffer &buffer, StreamPtr stream) const
931{
932    if (info == nullptr || buffer.buffer == nullptr || stream == nullptr) {
933        PKG_LOGE("CompressBuffer Param is null");
934        return PKG_INVALID_PARAM;
935    }
936    PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(info);
937    if (algorithm == nullptr) {
938        PKG_LOGE("CompressBuffer Can not get algorithm for %s", info->identity.c_str());
939        return PKG_INVALID_PARAM;
940    }
941
942    std::shared_ptr<MemoryMapStream> inStream = std::make_shared<MemoryMapStream>(
943        (PkgManager::PkgManagerPtr)this, info->identity, buffer, PkgStream::PkgStreamType_Buffer);
944    if (inStream == nullptr) {
945        PKG_LOGE("CompressBuffer Can not create stream for %s", info->identity.c_str());
946        return PKG_INVALID_PARAM;
947    }
948    PkgAlgorithmContext context = {{0, 0}, {0, buffer.length}, 0, info->digestMethod};
949    int32_t ret = algorithm->Pack(inStream.get(), PkgStreamImpl::ConvertPkgStream(stream), context);
950    if (ret != PKG_SUCCESS) {
951        PKG_LOGE("Fail Decompress for %s", info->identity.c_str());
952        return ret;
953    }
954    PKG_LOGI("packedSize: %zu unpackedSize: %zu ", context.packedSize, context.unpackedSize);
955    PkgStreamImpl::ConvertPkgStream(stream)->Flush(context.packedSize);
956    info->packedSize = context.packedSize;
957    info->unpackedSize = context.unpackedSize;
958    return PKG_SUCCESS;
959}
960
961void PkgManagerImpl::PostDecodeProgress(int type, size_t writeDataLen, const void *context)
962{
963    if (decodeProgress_ != nullptr) {
964        decodeProgress_(type, writeDataLen, context);
965    }
966}
967
968int32_t PkgManagerImpl::VerifyAccPackage(const std::string &packagePath, const std::string &keyPath)
969{
970    PkgStreamPtr pkgStream = nullptr;
971    int32_t ret = CreatePkgStream(pkgStream, packagePath, 0, PkgStream::PkgStreamType_Read);
972    if (ret != PKG_SUCCESS) {
973        PKG_LOGE("CreatePackage fail %s", packagePath.c_str());
974        UPDATER_LAST_WORD(PKG_INVALID_FILE);
975        return ret;
976    }
977
978    PkgVerifyUtil verifyUtil;
979    if (verifyUtil.VerifyPackageSign(pkgStream) != PKG_SUCCESS) {
980        ret = verifyUtil.VerifyAccPackageSign(pkgStream, keyPath);
981    }
982    if (ret != PKG_SUCCESS) {
983        PKG_LOGE("Verify zpkcs7 signature failed.");
984        UPDATER_LAST_WORD(packagePath, ret);
985        ClosePkgStream(pkgStream);
986        return ret;
987    }
988
989    ClosePkgStream(pkgStream);
990    return PKG_SUCCESS;
991}
992
993int32_t PkgManagerImpl::VerifyOtaPackage(const std::string &devPath, uint64_t offset, size_t size)
994{
995#ifndef DIFF_PATCH_SDK
996    constexpr size_t pageSize = 4096;
997    size_t offsetAligned = (offset / pageSize) * pageSize;
998    if (size == 0 || size + offset < offsetAligned || offset < offsetAligned) {
999        PKG_LOGE("invalid param %zu %" PRIu64 " %zu", size, offset, offsetAligned);
1000        return PKG_INVALID_PARAM;
1001    }
1002    char devRealPath[PATH_MAX + 1] = {};
1003    if (realpath(devPath.c_str(), devRealPath) == nullptr) {
1004        PKG_LOGE("realPath is nullptr, err %s", strerror(errno));
1005        return PKG_INVALID_PARAM;
1006    }
1007    int fd = open(devRealPath, O_RDONLY | O_LARGEFILE);
1008    if (fd < 0) {
1009        PKG_LOGE("open %s fail, %s", devRealPath, strerror(errno));
1010        return PKG_INVALID_FILE;
1011    }
1012    ON_SCOPE_EXIT(closePath) {
1013        close(fd);
1014    };
1015    uint8_t *pMap = static_cast<uint8_t *>(mmap64(nullptr, size + offset - offsetAligned, PROT_READ, MAP_PRIVATE,
1016        fd, offsetAligned));
1017    if (pMap == MAP_FAILED) {
1018        PKG_LOGE("mmap64 %s fail, %s %zu %" PRIu64, devRealPath, strerror(errno), size, offset);
1019        return PKG_NONE_MEMORY;
1020    }
1021    ON_SCOPE_EXIT(unmapMem) {
1022        munmap(pMap, size + offset - offsetAligned);
1023    };
1024    PkgBuffer buffer(pMap + (offset - offsetAligned), size);
1025    PkgStreamPtr pkgStream = nullptr;
1026    int32_t ret = CreatePkgStream(pkgStream, devRealPath, buffer);
1027    if (ret != PKG_SUCCESS) {
1028        PKG_LOGE("create package stream fail %s %s", devRealPath, strerror(errno));
1029        return ret;
1030    }
1031    ON_SCOPE_EXIT(closeStream) {
1032        ClosePkgStream(pkgStream);
1033    };
1034    PkgVerifyUtil verifyUtil {};
1035    ret = verifyUtil.VerifyPackageSign(pkgStream);
1036    if (ret != PKG_SUCCESS) {
1037        PKG_LOGE("verify pkcs7 signature failed.");
1038        return ret;
1039    }
1040#endif
1041    return PKG_SUCCESS;
1042}
1043
1044int32_t PkgManagerImpl::VerifyOtaPackage(const std::string &packagePath)
1045{
1046    PkgStreamPtr pkgStream = nullptr;
1047    int32_t ret = CreatePkgStream(pkgStream, packagePath, 0, PkgStream::PkgStreamType_Read);
1048    if (ret != PKG_SUCCESS) {
1049        PKG_LOGE("CreatePackage fail %s", packagePath.c_str());
1050        UPDATER_LAST_WORD(PKG_INVALID_FILE);
1051        return ret;
1052    }
1053
1054    PkgVerifyUtil verifyUtil;
1055    ret = verifyUtil.VerifyPackageSign(pkgStream);
1056    if (ret != PKG_SUCCESS) {
1057        PKG_LOGE("Verify zpkcs7 signature failed.");
1058        UPDATER_LAST_WORD(ret);
1059        ClosePkgStream(pkgStream);
1060        return ret;
1061    }
1062
1063    ClosePkgStream(pkgStream);
1064    return PKG_SUCCESS;
1065}
1066
1067int32_t PkgManagerImpl::VerifyBinFile(const std::string &packagePath, const std::string &keyPath,
1068    const std::string &version, const PkgBuffer &digest)
1069{
1070    PkgStreamPtr stream = nullptr;
1071    int32_t ret = CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read);
1072    if (ret != PKG_SUCCESS) {
1073        PKG_LOGE("Create input stream fail %s", packagePath.c_str());
1074        return ret;
1075    }
1076    size_t fileLen = stream->GetFileLength();
1077    if (fileLen <= 0) {
1078        PKG_LOGE("invalid file to load");
1079        ClosePkgStream(stream);
1080        return PKG_INVALID_FILE;
1081    }
1082
1083    int8_t digestMethod = static_cast<int8_t>(DigestAlgorithm::GetDigestMethod(version));
1084    size_t digestLen = DigestAlgorithm::GetDigestLen(digestMethod);
1085    size_t signatureLen = DigestAlgorithm::GetSignatureLen(digestMethod);
1086    if (digestLen != digest.length) {
1087        PKG_LOGE("Invalid digestLen");
1088        ClosePkgStream(stream);
1089        return PKG_INVALID_PARAM;
1090    }
1091    std::vector<std::vector<uint8_t>> digestInfos(DIGEST_INFO_SIGNATURE + 1);
1092    digestInfos[DIGEST_INFO_HAS_SIGN].resize(digestLen);
1093    digestInfos[DIGEST_INFO_NO_SIGN].resize(digestLen);
1094    digestInfos[DIGEST_INFO_SIGNATURE].resize(signatureLen);
1095
1096    ret = GenerateFileDigest(stream, digestMethod, DIGEST_FLAGS_HAS_SIGN, digestInfos);
1097    if (memcmp(digestInfos[DIGEST_INFO_HAS_SIGN].data(), digest.buffer, digest.length) != 0) {
1098        PKG_LOGE("Fail to verify package %s", packagePath.c_str());
1099        ret = PKG_INVALID_SIGNATURE;
1100    }
1101
1102    ClosePkgStream(stream);
1103    return ret;
1104}
1105} // namespace Hpackage
1106