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 "executor/zip_output.h"
16 #include <unistd.h>
17 #include "securec.h"
18 #include "dump_utils.h"
19 #include "util/file_utils.h"
20 #include "common/dumper_constant.h"
21 namespace OHOS {
22 namespace HiviewDFX {
ZipOutput()23 ZipOutput::ZipOutput() : fd_(-1)
24 {
25 }
26
~ZipOutput()27 ZipOutput::~ZipOutput()
28 {
29 if (fd_ >= 0) {
30 close(fd_);
31 }
32 }
33
PreExecute(const std::shared_ptr<DumperParameter> & parameter,StringMatrix dumpDatas)34 DumpStatus ZipOutput::PreExecute(const std::shared_ptr<DumperParameter>& parameter,
35 StringMatrix dumpDatas)
36 {
37 mDumpDatas_ = dumpDatas;
38 if (mDumpDatas_.get() == nullptr) {
39 return DumpStatus::DUMP_FAIL;
40 }
41
42 // init myself once
43 if (mFilePath_.empty()) {
44 mFilePath_ = parameter->GetOpts().path_;
45 srcBuffer_ = std::make_shared<CompressBuffer>();
46 destBuffer_ = std::make_shared<CompressBuffer>();
47 ClearBuffer();
48 fd_= DumpUtils::FdToWrite(mFilePath_);
49 if (fd_ < 0) {
50 return DumpStatus::DUMP_FAIL;
51 }
52 }
53
54 return DumpStatus::DUMP_OK;
55 }
56
Execute()57 DumpStatus ZipOutput::Execute()
58 {
59 DUMPER_HILOGI(MODULE_COMMON, "info|ZipOutput Execute");
60 if (!mDumpDatas_.get() || (fd_ < 0)) {
61 return DumpStatus::DUMP_FAIL;
62 }
63 CompressBuffer* srcBuffer = srcBuffer_.get();
64 CompressBuffer* destBuffer = destBuffer_.get();
65 if (!srcBuffer || !destBuffer) {
66 return DumpStatus::DUMP_FAIL;
67 }
68 DumpCompressor compressor;
69 for (auto v_line : *(mDumpDatas_.get())) {
70 // whole line
71 std::string line;
72 for (auto v_content : v_line) {
73 line.append(v_content);
74 }
75 const char* content = line.c_str();
76 uint16_t content_size = strlen(content);
77 uint16_t size = strlen(content) + 1; // include \n
78 // buffer is full
79 if ((srcBuffer->offset + size) > MAX_COMPRESS_BUFFER_SIZE) {
80 // compress and write to file
81 CompressAndWriteToFd();
82 }
83 // Process big line.
84 if (size > MAX_COMPRESS_BUFFER_SIZE) {
85 CompressAndWriteToFd(); // clear buffer
86 CompressBigLine(content, size);
87 continue;
88 }
89 // Add to buffer end with \n
90 if (memcpy_s(srcBuffer->content + srcBuffer->offset,
91 MAX_COMPRESS_BUFFER_SIZE - srcBuffer->offset, content, content_size) != EOK) {
92 LOG_DEBUG("ZipOutput::Execute() memcpy_s failed!\n");
93 return DumpStatus::DUMP_FAIL;
94 }
95 srcBuffer->offset = srcBuffer->offset + content_size;
96 srcBuffer->content[srcBuffer->offset] = '\n';
97 srcBuffer->offset = srcBuffer->offset + 1;
98 }
99 // compress and write to file
100 CompressAndWriteToFd();
101 // clear dump data.
102 mDumpDatas_->clear();
103 DUMPER_HILOGI(MODULE_COMMON, "info|ZipOutput Execute end");
104 return DumpStatus::DUMP_OK;
105 }
106
CompressAndWriteToFd()107 DumpStatus ZipOutput::CompressAndWriteToFd()
108 {
109 CompressBuffer* srcBuffer = srcBuffer_.get();
110 CompressBuffer* destBuffer = destBuffer_.get();
111 if (!srcBuffer || !destBuffer) {
112 return DumpStatus::DUMP_FAIL;
113 }
114 DumpStatus ret = DumpStatus::DUMP_OK;
115 if (srcBuffer->offset > 0) {
116 ret = compressor_.Compress(srcBuffer, destBuffer);
117 if (ret == DumpStatus::DUMP_OK) {
118 if (write(fd_, destBuffer->content, destBuffer->offset) < 0) {
119 ret = DumpStatus::DUMP_FAIL;
120 LOG_DEBUG("ZipOutput::CompressAndWriteToFd() Write to FD failed!\n");
121 }
122 } else {
123 ret = DumpStatus::DUMP_FAIL;
124 LOG_DEBUG("ZipOutput::CompressAndWriteToFd() Compress failed!\n");
125 }
126 ClearBuffer();
127 }
128
129 return ret;
130 }
131
CompressBigLine(const char * content,uint16_t size)132 DumpStatus ZipOutput::CompressBigLine(const char* content, uint16_t size)
133 {
134 if (!content) {
135 return DumpStatus::DUMP_FAIL;
136 }
137 CompressBuffer* srcBuffer = srcBuffer_.get();
138 CompressBuffer* destBuffer = destBuffer_.get();
139 if (!srcBuffer || !destBuffer) {
140 return DumpStatus::DUMP_FAIL;
141 }
142 DumpStatus ret = DumpStatus::DUMP_OK;
143 uint16_t remain_size = size - 1; // size include \n
144 uint16_t complete_size = 0;
145 while (remain_size > 0) {
146 uint16_t process_size = remain_size;
147 if ((srcBuffer->offset + remain_size) > MAX_COMPRESS_BUFFER_SIZE) {
148 process_size = MAX_COMPRESS_BUFFER_SIZE - srcBuffer->offset;
149 }
150 if (memcpy_s(srcBuffer->content + srcBuffer->offset,
151 MAX_COMPRESS_BUFFER_SIZE - srcBuffer->offset,
152 content + complete_size, process_size) != EOK) {
153 LOG_DEBUG("ZipOutput::CompressBigLine() memcpy_s failed!\n");
154 return DumpStatus::DUMP_FAIL;
155 }
156 srcBuffer->offset = srcBuffer->offset + process_size;
157 complete_size += process_size;
158 remain_size -= process_size;
159 CompressAndWriteToFd();
160 }
161 // process \n
162 srcBuffer->content[srcBuffer->offset] = '\n';
163 srcBuffer->offset = srcBuffer->offset + 1;
164 CompressAndWriteToFd();
165 return ret;
166 }
167
168
AfterExecute()169 DumpStatus ZipOutput::AfterExecute()
170 {
171 return DumpStatus::DUMP_OK;
172 }
173
ClearBuffer()174 void ZipOutput::ClearBuffer()
175 {
176 if (srcBuffer_.get()) {
177 (void)memset_s(srcBuffer_.get(), sizeof(CompressBuffer), 0, sizeof(CompressBuffer));
178 }
179 if (destBuffer_.get()) {
180 (void)memset_s(destBuffer_.get(), sizeof(CompressBuffer), 0, sizeof(CompressBuffer));
181 }
182 }
183 } // namespace HiviewDFX
184 } // namespace OHOS
185