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 "util/dump_compressor.h"
16 #include <securec.h>
17
18 using namespace std;
19 namespace OHOS {
20 namespace HiviewDFX {
DumpCompressor()21 DumpCompressor::DumpCompressor()
22 {
23 }
24
Init(CompressBuffer * & srcBuffer)25 DumpStatus DumpCompressor::Init(CompressBuffer*& srcBuffer)
26 {
27 uint32_t bound = compressBound(srcBuffer->offset);
28 if (bound == 0) {
29 return DumpStatus::DUMP_FAIL;
30 }
31 zDataSize_ = (bound < CHUNK) ? CHUNK : bound;
32 zData_ = new unsigned char[zDataSize_];
33 if (zData_ == nullptr) {
34 return DumpStatus::DUMP_FAIL;
35 }
36 if (memset_s(zData_, zDataSize_, 0, zDataSize_) != EOK) {
37 DeleteZData();
38 return DumpStatus::DUMP_FAIL;
39 };
40
41 zStream_.zalloc = Z_NULL;
42 zStream_.zfree = Z_NULL;
43 zStream_.opaque = Z_NULL;
44
45 if (deflateInit2(&zStream_, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + WINDOWS_BITS,
46 MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) {
47 DeleteZData();
48 return DumpStatus::DUMP_FAIL;
49 }
50 return DumpStatus::DUMP_OK;
51 }
52
DeleteZData()53 void DumpCompressor::DeleteZData()
54 {
55 if (zData_ != nullptr) {
56 delete[] zData_;
57 };
58 zData_ = nullptr;
59 }
DeleteZBuff(char * buffIn,char * buffOut)60 void DumpCompressor::DeleteZBuff(char* buffIn, char* buffOut)
61 {
62 delete[] buffIn;
63 delete[] buffOut;
64 buffIn = nullptr;
65 buffOut = nullptr;
66 }
Compress(CompressBuffer * & srcBuffer,CompressBuffer * & destBuffer)67 DumpStatus DumpCompressor::Compress(CompressBuffer*& srcBuffer, CompressBuffer*& destBuffer)
68 {
69 if (Init(srcBuffer) != DumpStatus::DUMP_OK) {
70 return DumpStatus::DUMP_FAIL;
71 }
72 size_t const toRead = CHUNK;
73 size_t srcPos = 0;
74 size_t dstPos = 0;
75 size_t srcBufferOffset = srcBuffer->offset;
76 int flush = 0;
77 char* buffIn = new char[CHUNK];
78 char* buffOut = new char[CHUNK];
79 if (buffIn == nullptr || buffOut == nullptr) {
80 return DumpStatus::DUMP_FAIL;
81 }
82 if (memset_s(buffIn, CHUNK, 0, CHUNK) != EOK ||
83 memset_s(buffOut, CHUNK, 0, CHUNK) != EOK) {
84 DeleteZBuff(buffIn, buffOut);
85 return DumpStatus::DUMP_FAIL;
86 };
87
88 do {
89 if (FillBuffer(flush, srcBuffer, buffIn, toRead, srcPos, srcBufferOffset) == DumpStatus::DUMP_FAIL) {
90 DeleteZBuff(buffIn, buffOut);
91 return DumpStatus::DUMP_FAIL;
92 }
93 if (DeflateBuffer(flush, buffOut, dstPos) == DumpStatus::DUMP_FAIL) {
94 DeleteZBuff(buffIn, buffOut);
95 return DumpStatus::DUMP_FAIL;
96 }
97 } while (flush != Z_FINISH);
98
99 /* clean up and return */
100 (void)deflateEnd(&zStream_);
101
102 if (memcpy_s(destBuffer->content + destBuffer->offset,
103 MAX_COMPRESS_BUFFER_SIZE - destBuffer->offset, zData_, dstPos) != EOK) {
104 DeleteZData();
105 return DumpStatus::DUMP_FAIL;
106 }
107 destBuffer->offset += dstPos;
108 DeleteZData();
109 DeleteZBuff(buffIn, buffOut);
110 return DumpStatus::DUMP_OK;
111 }
112
FillBuffer(int & flush,CompressBuffer * & srcBuffer,char * buffIn,size_t const toRead,size_t & src_pos,size_t srcBufferOffset)113 DumpStatus DumpCompressor::FillBuffer(int& flush, CompressBuffer*& srcBuffer, char* buffIn,
114 size_t const toRead, size_t& src_pos, size_t srcBufferOffset)
115 {
116 bool flag = (srcBufferOffset - src_pos) < toRead;
117 (void)memset_s(buffIn, CHUNK, 0, CHUNK);
118
119 if (flag) {
120 if (memmove_s(buffIn, CHUNK, srcBuffer->content + src_pos, srcBufferOffset - src_pos) != EOK) {
121 DeleteZData();
122 return DumpStatus::DUMP_FAIL;
123 }
124 zStream_.avail_in = srcBufferOffset - src_pos;
125 src_pos += srcBufferOffset - src_pos;
126 } else {
127 if (memmove_s(buffIn, CHUNK, srcBuffer->content + src_pos, toRead) != EOK) {
128 DeleteZData();
129 return DumpStatus::DUMP_FAIL;
130 };
131 zStream_.avail_in = toRead;
132 src_pos += toRead;
133 }
134
135 flush = flag ? Z_FINISH : Z_NO_FLUSH;
136 zStream_.next_in = (Bytef*)buffIn;
137 return DumpStatus::DUMP_OK;
138 }
139
DeflateBuffer(int flush,char * buffOut,size_t & dstPos)140 DumpStatus DumpCompressor::DeflateBuffer(int flush, char* buffOut, size_t& dstPos)
141 {
142 /* run deflate() on input , finish compression until all of source has been read in. */
143 do {
144 zStream_.avail_out = CHUNK;
145 zStream_.next_out = (Bytef*)buffOut;
146 if (deflate(&zStream_, flush) == Z_STREAM_ERROR) {
147 DeleteZData();
148 return DumpStatus::DUMP_FAIL;
149 }
150 unsigned have = CHUNK - zStream_.avail_out;
151 if (memmove_s(zData_ + dstPos, zDataSize_ - dstPos, buffOut, have) != EOK) {
152 DeleteZData();
153 return DumpStatus::DUMP_FAIL;
154 }
155 dstPos += have;
156 } while (zStream_.avail_out == 0);
157
158 return DumpStatus::DUMP_OK;
159 }
160 } // namespace HiviewDFX
161 } // namespace OHOS
162