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