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_pkgfile.h"
16fb299fa2Sopenharmony_ci#include <ctime>
17fb299fa2Sopenharmony_ci#include <limits>
18fb299fa2Sopenharmony_ci#include <memory>
19fb299fa2Sopenharmony_ci#include "dump.h"
20fb299fa2Sopenharmony_ci#include "pkg_gzipfile.h"
21fb299fa2Sopenharmony_ci#include "pkg_lz4file.h"
22fb299fa2Sopenharmony_ci#include "pkg_stream.h"
23fb299fa2Sopenharmony_ci#include "pkg_upgradefile.h"
24fb299fa2Sopenharmony_ci#include "pkg_utils.h"
25fb299fa2Sopenharmony_ci#include "pkg_zipfile.h"
26fb299fa2Sopenharmony_ci
27fb299fa2Sopenharmony_cinamespace Hpackage {
28fb299fa2Sopenharmony_ciPkgFileImpl::~PkgFileImpl()
29fb299fa2Sopenharmony_ci{
30fb299fa2Sopenharmony_ci    auto iter = pkgEntryMapId_.begin();
31fb299fa2Sopenharmony_ci    while (iter != pkgEntryMapId_.end()) {
32fb299fa2Sopenharmony_ci        auto entry = iter->second;
33fb299fa2Sopenharmony_ci        delete entry;
34fb299fa2Sopenharmony_ci        iter = pkgEntryMapId_.erase(iter);
35fb299fa2Sopenharmony_ci    }
36fb299fa2Sopenharmony_ci    pkgEntryMapId_.clear();
37fb299fa2Sopenharmony_ci    pkgEntryMapFileName_.clear();
38fb299fa2Sopenharmony_ci    PkgManager::StreamPtr tmpStream = pkgStream_;
39fb299fa2Sopenharmony_ci    pkgManager_->ClosePkgStream(tmpStream);
40fb299fa2Sopenharmony_ci}
41fb299fa2Sopenharmony_ci
42fb299fa2Sopenharmony_ciPkgEntryPtr PkgFileImpl::AddPkgEntry(const std::string &fileName)
43fb299fa2Sopenharmony_ci{
44fb299fa2Sopenharmony_ci    uint32_t nodeId = ++nodeId_;
45fb299fa2Sopenharmony_ci    PkgEntryPtr entry = nullptr;
46fb299fa2Sopenharmony_ci    switch (type_) {
47fb299fa2Sopenharmony_ci        case PKG_TYPE_UPGRADE:
48fb299fa2Sopenharmony_ci            entry = new UpgradeFileEntry(this, nodeId);
49fb299fa2Sopenharmony_ci            break;
50fb299fa2Sopenharmony_ci        case PKG_TYPE_ZIP:
51fb299fa2Sopenharmony_ci            entry = new ZipFileEntry(this, nodeId);
52fb299fa2Sopenharmony_ci            break;
53fb299fa2Sopenharmony_ci        case PKG_TYPE_LZ4: {
54fb299fa2Sopenharmony_ci            entry = new Lz4FileEntry(this, nodeId);
55fb299fa2Sopenharmony_ci            break;
56fb299fa2Sopenharmony_ci        }
57fb299fa2Sopenharmony_ci        case PKG_TYPE_GZIP: {
58fb299fa2Sopenharmony_ci            entry = new GZipFileEntry(this, nodeId);
59fb299fa2Sopenharmony_ci            break;
60fb299fa2Sopenharmony_ci        }
61fb299fa2Sopenharmony_ci        default:
62fb299fa2Sopenharmony_ci            return nullptr;
63fb299fa2Sopenharmony_ci    }
64fb299fa2Sopenharmony_ci    pkgEntryMapId_.insert(std::pair<uint32_t, PkgEntryPtr>(nodeId, entry));
65fb299fa2Sopenharmony_ci    pkgEntryMapFileName_.insert(std::pair<std::string, PkgEntryPtr>(fileName, entry));
66fb299fa2Sopenharmony_ci    return entry;
67fb299fa2Sopenharmony_ci}
68fb299fa2Sopenharmony_ci
69fb299fa2Sopenharmony_ciint32_t PkgFileImpl::ExtractFile(const PkgEntryPtr node, PkgStreamPtr output)
70fb299fa2Sopenharmony_ci{
71fb299fa2Sopenharmony_ci    PKG_LOGI("ExtractFile %s", output->GetFileName().c_str());
72fb299fa2Sopenharmony_ci    if (!CheckState({PKG_FILE_STATE_WORKING}, PKG_FILE_STATE_WORKING)) {
73fb299fa2Sopenharmony_ci        PKG_LOGE("error state curr %d ", state_);
74fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(PKG_INVALID_STATE);
75fb299fa2Sopenharmony_ci        return PKG_INVALID_STATE;
76fb299fa2Sopenharmony_ci    }
77fb299fa2Sopenharmony_ci    auto entry = static_cast<PkgEntryPtr>(node);
78fb299fa2Sopenharmony_ci    if (entry == nullptr) {
79fb299fa2Sopenharmony_ci        PKG_LOGE("error get entry %s", pkgStream_->GetFileName().c_str());
80fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(PKG_INVALID_PARAM);
81fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
82fb299fa2Sopenharmony_ci    }
83fb299fa2Sopenharmony_ci    return entry->Unpack(output);
84fb299fa2Sopenharmony_ci}
85fb299fa2Sopenharmony_ci
86fb299fa2Sopenharmony_ciPkgEntryPtr PkgFileImpl::FindPkgEntry(const std::string &fileName)
87fb299fa2Sopenharmony_ci{
88fb299fa2Sopenharmony_ci    if (!CheckState({PKG_FILE_STATE_WORKING}, PKG_FILE_STATE_WORKING)) {
89fb299fa2Sopenharmony_ci        PKG_LOGE("error state curr %d ", state_);
90fb299fa2Sopenharmony_ci        return nullptr;
91fb299fa2Sopenharmony_ci    }
92fb299fa2Sopenharmony_ci    std::multimap<std::string, PkgEntryPtr>::iterator iter = pkgEntryMapFileName_.find(fileName);
93fb299fa2Sopenharmony_ci    if (iter != pkgEntryMapFileName_.end()) {
94fb299fa2Sopenharmony_ci        return (*iter).second;
95fb299fa2Sopenharmony_ci    }
96fb299fa2Sopenharmony_ci    return nullptr;
97fb299fa2Sopenharmony_ci}
98fb299fa2Sopenharmony_ci
99fb299fa2Sopenharmony_cibool PkgFileImpl::CheckState(std::vector<uint32_t> states, uint32_t state)
100fb299fa2Sopenharmony_ci{
101fb299fa2Sopenharmony_ci    bool ret = false;
102fb299fa2Sopenharmony_ci    for (auto s : states) {
103fb299fa2Sopenharmony_ci        if (state_ == s) {
104fb299fa2Sopenharmony_ci            state_ = state;
105fb299fa2Sopenharmony_ci            ret = true;
106fb299fa2Sopenharmony_ci            break;
107fb299fa2Sopenharmony_ci        }
108fb299fa2Sopenharmony_ci    }
109fb299fa2Sopenharmony_ci    return ret;
110fb299fa2Sopenharmony_ci}
111fb299fa2Sopenharmony_ci
112fb299fa2Sopenharmony_ciint32_t PkgFileImpl::ConvertBufferToString(std::string &fileName, const PkgBuffer &buffer)
113fb299fa2Sopenharmony_ci{
114fb299fa2Sopenharmony_ci    for (uint32_t i = 0; i < buffer.length; ++i) {
115fb299fa2Sopenharmony_ci        if (buffer.buffer[i] < 32 || buffer.buffer[i] >= 127) { // 32,127 : should be printable character
116fb299fa2Sopenharmony_ci            break;
117fb299fa2Sopenharmony_ci        }
118fb299fa2Sopenharmony_ci        fileName.push_back(buffer.buffer[i]);
119fb299fa2Sopenharmony_ci    }
120fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
121fb299fa2Sopenharmony_ci}
122fb299fa2Sopenharmony_ci
123fb299fa2Sopenharmony_ciint32_t PkgFileImpl::ConvertStringToBuffer(const std::string &fileName, const PkgBuffer &buffer, size_t &realLen)
124fb299fa2Sopenharmony_ci{
125fb299fa2Sopenharmony_ci    if (buffer.length < fileName.size()) {
126fb299fa2Sopenharmony_ci        PKG_LOGE("Invalid buffer");
127fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
128fb299fa2Sopenharmony_ci    }
129fb299fa2Sopenharmony_ci    for (uint32_t i = 0; i < fileName.size(); ++i) {
130fb299fa2Sopenharmony_ci        buffer.buffer[i] = static_cast<uint8_t>(fileName[i]);
131fb299fa2Sopenharmony_ci        (realLen)++;
132fb299fa2Sopenharmony_ci    }
133fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
134fb299fa2Sopenharmony_ci}
135fb299fa2Sopenharmony_ci
136fb299fa2Sopenharmony_ciint32_t PkgEntry::Init(PkgManager::FileInfoPtr localFileInfo, const PkgManager::FileInfoPtr fileInfo,
137fb299fa2Sopenharmony_ci    PkgStreamPtr inStream)
138fb299fa2Sopenharmony_ci{
139fb299fa2Sopenharmony_ci    if (localFileInfo == nullptr || fileInfo == nullptr || inStream == nullptr) {
140fb299fa2Sopenharmony_ci        PKG_LOGE("Failed to check input param");
141fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
142fb299fa2Sopenharmony_ci    }
143fb299fa2Sopenharmony_ci
144fb299fa2Sopenharmony_ci    fileName_.assign(inStream->GetFileName());
145fb299fa2Sopenharmony_ci    localFileInfo->identity.assign(fileInfo->identity);
146fb299fa2Sopenharmony_ci    localFileInfo->flags = fileInfo->flags;
147fb299fa2Sopenharmony_ci    localFileInfo->digestMethod = fileInfo->digestMethod;
148fb299fa2Sopenharmony_ci    localFileInfo->packMethod = fileInfo->packMethod;
149fb299fa2Sopenharmony_ci    localFileInfo->modifiedTime = fileInfo->modifiedTime;
150fb299fa2Sopenharmony_ci    localFileInfo->packedSize = fileInfo->packedSize;
151fb299fa2Sopenharmony_ci    localFileInfo->unpackedSize = fileInfo->unpackedSize;
152fb299fa2Sopenharmony_ci
153fb299fa2Sopenharmony_ci    // 填充file信息,默认值使用原始文件长度
154fb299fa2Sopenharmony_ci    if (localFileInfo->unpackedSize == 0) {
155fb299fa2Sopenharmony_ci        localFileInfo->unpackedSize = inStream->GetFileLength();
156fb299fa2Sopenharmony_ci    }
157fb299fa2Sopenharmony_ci    if (localFileInfo->packedSize == 0) {
158fb299fa2Sopenharmony_ci        localFileInfo->packedSize = inStream->GetFileLength();
159fb299fa2Sopenharmony_ci    }
160fb299fa2Sopenharmony_ci    if (localFileInfo->unpackedSize == 0) {
161fb299fa2Sopenharmony_ci        PKG_LOGE("Failed to check unpackedSize = 0");
162fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
163fb299fa2Sopenharmony_ci    }
164fb299fa2Sopenharmony_ci    if (localFileInfo->modifiedTime == 0) {
165fb299fa2Sopenharmony_ci        time(&localFileInfo->modifiedTime);
166fb299fa2Sopenharmony_ci    }
167fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
168fb299fa2Sopenharmony_ci}
169fb299fa2Sopenharmony_ci
170fb299fa2Sopenharmony_civoid PkgFileImpl::AddSignData(uint8_t digestMethod, size_t currOffset, size_t &signOffset)
171fb299fa2Sopenharmony_ci{
172fb299fa2Sopenharmony_ci    signOffset = currOffset;
173fb299fa2Sopenharmony_ci    if (digestMethod == PKG_DIGEST_TYPE_NONE) {
174fb299fa2Sopenharmony_ci        return;
175fb299fa2Sopenharmony_ci    }
176fb299fa2Sopenharmony_ci    std::vector<uint8_t> buffer(SIGN_SHA256_LEN + SIGN_SHA384_LEN, 0);
177fb299fa2Sopenharmony_ci    int32_t ret = pkgStream_->Write(buffer, buffer.size(), currOffset);
178fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
179fb299fa2Sopenharmony_ci        PKG_LOGE("Fail write sign for %s", pkgStream_->GetFileName().c_str());
180fb299fa2Sopenharmony_ci        return;
181fb299fa2Sopenharmony_ci    }
182fb299fa2Sopenharmony_ci    pkgStream_->Flush(currOffset + buffer.size());
183fb299fa2Sopenharmony_ci    PKG_LOGI("SavePackage success file length: %zu signOffset %zu", pkgStream_->GetFileLength(), signOffset);
184fb299fa2Sopenharmony_ci}
185fb299fa2Sopenharmony_ci} // namespace Hpackage
186