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 if (!mDumpDatas_.get() || (fd_ < 0)) {
60 return DumpStatus::DUMP_FAIL;
61 }
62 CompressBuffer* srcBuffer = srcBuffer_.get();
63 CompressBuffer* destBuffer = destBuffer_.get();
64 if (!srcBuffer || !destBuffer) {
65 return DumpStatus::DUMP_FAIL;
66 }
67 DumpCompressor compressor;
68 for (auto v_line : *(mDumpDatas_.get())) {
69 // whole line
70 std::string line;
71 for (auto v_content : v_line) {
72 line.append(v_content);
73 }
74 const char* content = line.c_str();
75 uint16_t content_size = strlen(content);
76 uint16_t size = strlen(content) + 1; // include \n
77 // buffer is full
78 if ((srcBuffer->offset + size) > MAX_COMPRESS_BUFFER_SIZE) {
79 // compress and write to file
80 CompressAndWriteToFd();
81 }
82 // Process big line.
83 if (size > MAX_COMPRESS_BUFFER_SIZE) {
84 CompressAndWriteToFd(); // clear buffer
85 CompressBigLine(content, size);
86 continue;
87 }
88 // Add to buffer end with \n
89 if (memcpy_s(srcBuffer->content + srcBuffer->offset,
90 MAX_COMPRESS_BUFFER_SIZE - srcBuffer->offset, content, content_size) != EOK) {
91 LOG_DEBUG("ZipOutput::Execute() memcpy_s failed!\n");
92 return DumpStatus::DUMP_FAIL;
93 }
94 srcBuffer->offset = srcBuffer->offset + content_size;
95 srcBuffer->content[srcBuffer->offset] = '\n';
96 srcBuffer->offset = srcBuffer->offset + 1;
97 }
98 // compress and write to file
99 CompressAndWriteToFd();
100 // clear dump data.
101 mDumpDatas_->clear();
102 return DumpStatus::DUMP_OK;
103 }
104
CompressAndWriteToFd()105 DumpStatus ZipOutput::CompressAndWriteToFd()
106 {
107 CompressBuffer* srcBuffer = srcBuffer_.get();
108 CompressBuffer* destBuffer = destBuffer_.get();
109 if (!srcBuffer || !destBuffer) {
110 return DumpStatus::DUMP_FAIL;
111 }
112 DumpStatus ret = DumpStatus::DUMP_OK;
113 if (srcBuffer->offset > 0) {
114 ret = compressor_.Compress(srcBuffer, destBuffer);
115 if (ret == DumpStatus::DUMP_OK) {
116 if (write(fd_, destBuffer->content, destBuffer->offset) < 0) {
117 ret = DumpStatus::DUMP_FAIL;
118 LOG_DEBUG("ZipOutput::CompressAndWriteToFd() Write to FD failed!\n");
119 }
120 } else {
121 ret = DumpStatus::DUMP_FAIL;
122 LOG_DEBUG("ZipOutput::CompressAndWriteToFd() Compress failed!\n");
123 }
124 ClearBuffer();
125 }
126
127 return ret;
128 }
129
CompressBigLine(const char * content,uint16_t size)130 DumpStatus ZipOutput::CompressBigLine(const char* content, uint16_t size)
131 {
132 if (!content) {
133 return DumpStatus::DUMP_FAIL;
134 }
135 CompressBuffer* srcBuffer = srcBuffer_.get();
136 CompressBuffer* destBuffer = destBuffer_.get();
137 if (!srcBuffer || !destBuffer) {
138 return DumpStatus::DUMP_FAIL;
139 }
140 DumpStatus ret = DumpStatus::DUMP_OK;
141 uint16_t remain_size = size - 1; // size include \n
142 uint16_t complete_size = 0;
143 while (remain_size > 0) {
144 uint16_t process_size = remain_size;
145 if ((srcBuffer->offset + remain_size) > MAX_COMPRESS_BUFFER_SIZE) {
146 process_size = MAX_COMPRESS_BUFFER_SIZE - srcBuffer->offset;
147 }
148 if (memcpy_s(srcBuffer->content + srcBuffer->offset,
149 MAX_COMPRESS_BUFFER_SIZE - srcBuffer->offset,
150 content + complete_size, process_size) != EOK) {
151 LOG_DEBUG("ZipOutput::CompressBigLine() memcpy_s failed!\n");
152 return DumpStatus::DUMP_FAIL;
153 }
154 srcBuffer->offset = srcBuffer->offset + process_size;
155 complete_size += process_size;
156 remain_size -= process_size;
157 CompressAndWriteToFd();
158 }
159 // process \n
160 srcBuffer->content[srcBuffer->offset] = '\n';
161 srcBuffer->offset = srcBuffer->offset + 1;
162 CompressAndWriteToFd();
163 return ret;
164 }
165
166
AfterExecute()167 DumpStatus ZipOutput::AfterExecute()
168 {
169 return DumpStatus::DUMP_OK;
170 }
171
ClearBuffer()172 void ZipOutput::ClearBuffer()
173 {
174 if (srcBuffer_.get()) {
175 (void)memset_s(srcBuffer_.get(), sizeof(CompressBuffer), 0, sizeof(CompressBuffer));
176 }
177 if (destBuffer_.get()) {
178 (void)memset_s(destBuffer_.get(), sizeof(CompressBuffer), 0, sizeof(CompressBuffer));
179 }
180 }
181 } // namespace HiviewDFX
182 } // namespace OHOS
183