• 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 #include "pkg_algorithm.h"
16 #include "pkg_algo_deflate.h"
17 #include "pkg_algo_lz4.h"
18 #include "pkg_stream.h"
19 #include "pkg_utils.h"
20 #include "securec.h"
21 
22 namespace hpackage {
23 constexpr uint32_t MAX_BUFFER_SIZE = (4 * 1024 * 1024);
24 
ReadData(const PkgStreamPtr inStream,size_t offset,PkgBuffer & buffer,size_t & remainSize,size_t & readLen) const25 int32_t PkgAlgorithm::ReadData(const PkgStreamPtr inStream, size_t offset, PkgBuffer &buffer,
26     size_t &remainSize, size_t &readLen) const
27 {
28     size_t readBytes = 0;
29     size_t remainBytes = (remainSize > buffer.length) ? buffer.length : remainSize;
30     if (remainBytes != 0) {
31         int32_t ret = inStream->Read(buffer, offset, remainBytes, readBytes);
32         PKG_CHECK(ret == PKG_SUCCESS, return ret, "fail deflate write data ");
33     }
34     remainSize -= readBytes;
35     readLen = readBytes;
36     return PKG_SUCCESS;
37 }
38 
FinalDigest(DigestAlgorithm::DigestAlgorithmPtr algorithm,PkgAlgorithmContext & context,bool check) const39 int32_t PkgAlgorithm::FinalDigest(DigestAlgorithm::DigestAlgorithmPtr algorithm,
40     PkgAlgorithmContext &context, bool check) const
41 {
42     if (context.digestMethod == PKG_DIGEST_TYPE_SHA256) {
43         PkgBuffer digest(DIGEST_MAX_LEN);
44         algorithm->Final(digest);
45         if (check && memcmp(digest.buffer, context.digest, DIGEST_MAX_LEN) != 0) {
46             return PKG_INVALID_DIGEST;
47         }
48         PKG_CHECK(!memcpy_s(context.digest, sizeof(context.digest), digest.buffer, DIGEST_MAX_LEN),
49             return PKG_NONE_MEMORY, "FinalDigest memcpy failed");
50     }
51     return PKG_SUCCESS;
52 }
53 
Pack(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgAlgorithmContext & context)54 int32_t PkgAlgorithm::Pack(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
55     PkgAlgorithmContext &context)
56 {
57     DigestAlgorithm::DigestAlgorithmPtr algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(context.digestMethod);
58     PKG_CHECK(algorithm != nullptr, return PKG_NOT_EXIST_ALGORITHM, "Can not get digest algor");
59     algorithm->Init();
60 
61     PkgBuffer buffer(MAX_BUFFER_SIZE);
62     int32_t ret = PKG_SUCCESS;
63     size_t srcOffset = context.srcOffset;
64     size_t destOffset = context.destOffset;
65     size_t remainSize = context.unpackedSize;
66     size_t readLen = 0;
67     while (remainSize > 0) {
68         ret = ReadData(inStream, srcOffset, buffer, remainSize, readLen);
69         PKG_CHECK(ret == PKG_SUCCESS, break, "Fail read data ");
70 
71         ret = outStream->Write(buffer, readLen, destOffset);
72         PKG_CHECK(ret == PKG_SUCCESS, break, "Fail write data ");
73 
74         algorithm->Update(buffer, readLen);
75         srcOffset += readLen;
76         destOffset += readLen;
77     }
78 
79     ret = FinalDigest(algorithm, context, true);
80     PKG_CHECK(ret == 0, return ret, "Check digest fail");
81     PKG_CHECK(srcOffset - context.srcOffset == context.unpackedSize, return PKG_INVALID_STREAM,
82         "original size error %zu %zu", srcOffset, context.unpackedSize);
83     context.packedSize = destOffset - context.destOffset;
84     return ret;
85 }
86 
Unpack(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgAlgorithmContext & context)87 int32_t PkgAlgorithm::Unpack(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
88     PkgAlgorithmContext &context)
89 {
90     DigestAlgorithm::DigestAlgorithmPtr algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(context.digestMethod);
91     PKG_CHECK(algorithm != nullptr, return PKG_NOT_EXIST_ALGORITHM, "Can not get digest algor");
92     algorithm->Init();
93     PkgBuffer buffer(MAX_BUFFER_SIZE);
94     int32_t ret = PKG_SUCCESS;
95     size_t srcOffset = context.srcOffset;
96     size_t destOffset = context.destOffset;
97     size_t remainSize = context.packedSize;
98     size_t readLen = 0;
99     while (remainSize > 0) {
100         ret = ReadData(inStream, srcOffset, buffer, remainSize, readLen);
101         PKG_CHECK(ret == PKG_SUCCESS, break, "Fail read data ");
102 
103         ret = outStream->Write(buffer, readLen, destOffset);
104         PKG_CHECK(ret == PKG_SUCCESS, break, "Fail write data ");
105 
106         algorithm->Update(buffer, readLen);
107         srcOffset += readLen;
108         destOffset += readLen;
109     }
110 
111     ret = FinalDigest(algorithm, context, true);
112     PKG_CHECK(ret == 0, return ret, "Check digest fail");
113     PKG_CHECK(destOffset - context.destOffset == context.packedSize, return PKG_INVALID_STREAM,
114         "original size error %zu %zu", destOffset, context.packedSize);
115     context.unpackedSize = srcOffset - context.srcOffset;
116     return ret;
117 }
118 
GetAlgorithm(const PkgManager::FileInfoPtr config)119 PkgAlgorithm::PkgAlgorithmPtr PkgAlgorithmFactory::GetAlgorithm(const PkgManager::FileInfoPtr config)
120 {
121     PKG_CHECK(config != nullptr, return nullptr, "Fail to get algorithm ");
122     switch (config->packMethod) {
123         case PKG_COMPRESS_METHOD_ZIP:
124         case PKG_COMPRESS_METHOD_GZIP: {
125             PKG_CHECK(config != nullptr, return nullptr, "Invalid param config");
126             const ZipFileInfo *info = (ZipFileInfo *)config;
127             return std::make_shared<PkgAlgoDeflate>(*info);
128         }
129         case PKG_COMPRESS_METHOD_NONE:
130             return std::make_shared<PkgAlgorithm>();
131         case PKG_COMPRESS_METHOD_LZ4: {
132             PKG_CHECK(config != nullptr, return nullptr, "Invalid param config");
133             const Lz4FileInfo *info = (Lz4FileInfo *)config;
134             return std::make_shared<PkgAlgorithmLz4>(*info);
135         }
136         case PKG_COMPRESS_METHOD_LZ4_BLOCK: {
137             PKG_CHECK(config != nullptr, return nullptr, "Invalid param config");
138             const Lz4FileInfo *info = (Lz4FileInfo *)config;
139             return std::make_shared<PkgAlgorithmBlockLz4>(*info);
140         }
141         default:
142             break;
143     }
144     return nullptr;
145 }
146 } // namespace hpackage
147