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