1 /*
2 * Copyright (c) 2021-2025 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
16 #include "dfx_buffer_writer.h"
17
18 #include <securec.h>
19 #ifndef is_ohos_lite
20 #include <string_ex.h>
21 #endif // !is_ohos_lite
22 #include <unistd.h>
23
24 #include "dfx_log.h"
25 #include "dfx_define.h"
26 #include "dfx_util.h"
27
28 namespace OHOS {
29 namespace HiviewDFX {
30
GetInstance()31 DfxBufferWriter &DfxBufferWriter::GetInstance()
32 {
33 static DfxBufferWriter ins;
34 return ins;
35 }
36
WriteMsg(const std::string & msg)37 void DfxBufferWriter::WriteMsg(const std::string& msg)
38 {
39 if (writeFunc_ == nullptr) {
40 writeFunc_ = DfxBufferWriter::DefaultWrite;
41 }
42 constexpr size_t step = 1024 * 1024;
43 for (size_t i = 0; i < msg.size(); i += step) {
44 size_t length = (i + step) < msg.size() ? step : msg.size() - i;
45 writeFunc_(bufFd_.GetFd(), msg.substr(i, length).c_str(), length);
46 }
47 }
48
WriteDumpRes(int32_t dumpRes)49 bool DfxBufferWriter::WriteDumpRes(int32_t dumpRes)
50 {
51 if (!resFd_) {
52 return false;
53 }
54 ssize_t nwrite = OHOS_TEMP_FAILURE_RETRY(write(resFd_.GetFd(), &dumpRes, sizeof(dumpRes)));
55 if (nwrite != static_cast<ssize_t>(sizeof(dumpRes))) {
56 DFXLOGE("%{public}s write fail, err:%{public}d", __func__, errno);
57 return false;
58 }
59 return true;
60 }
61
WriteFormatMsg(const char * format,...)62 void DfxBufferWriter::WriteFormatMsg(const char *format, ...)
63 {
64 char buf[LINE_BUF_SIZE] = {0};
65 va_list args;
66 va_start(args, format);
67 int ret = vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, format, args);
68 va_end(args);
69 if (ret < 0) {
70 DFXLOGE("%{public}s :: vsnprintf_s failed, line: %{public}d.", __func__, __LINE__);
71 return;
72 }
73 WriteMsg(std::string(buf));
74 }
75
AppendBriefDumpInfo(const std::string & info)76 void DfxBufferWriter::AppendBriefDumpInfo(const std::string& info)
77 {
78 briefDumpInfo_.append(info);
79 }
80
PrintBriefDumpInfo()81 void DfxBufferWriter::PrintBriefDumpInfo()
82 {
83 #ifndef is_ohos_lite
84 if (briefDumpInfo_.empty()) {
85 DFXLOGE("crash base info is empty");
86 }
87 std::vector<std::string> dumpInfoLines;
88
89 OHOS::SplitStr(briefDumpInfo_, "\n", dumpInfoLines);
90 for (const auto& dumpInfoLine : dumpInfoLines) {
91 DFXLOGI("%{public}s", dumpInfoLine.c_str());
92 }
93 #endif
94 }
95
Finish()96 void DfxBufferWriter::Finish()
97 {
98 if (bufFd_ && fsync(bufFd_.GetFd()) == -1) {
99 DFXLOGW("Failed to fsync fd.");
100 }
101 }
102
SetWriteResFd(SmartFd fd)103 void DfxBufferWriter::SetWriteResFd(SmartFd fd)
104 {
105 if (!fd) {
106 DFXLOGE("invalid res fd, failed to set fd.\n");
107 return;
108 }
109 resFd_ = std::move(fd);
110 }
111
SetWriteBufFd(SmartFd fd)112 void DfxBufferWriter::SetWriteBufFd(SmartFd fd)
113 {
114 if (!fd) {
115 DFXLOGE("invalid buffer fd, failed to set fd.\n");
116 return;
117 }
118 bufFd_ = std::move(fd);
119 }
120
SetWriteFunc(BufferWriteFunc func)121 void DfxBufferWriter::SetWriteFunc(BufferWriteFunc func)
122 {
123 writeFunc_ = func;
124 }
125
DefaultWrite(int32_t fd,const char * buf,const size_t len)126 int DfxBufferWriter::DefaultWrite(int32_t fd, const char *buf, const size_t len)
127 {
128 if (buf == nullptr) {
129 return -1;
130 }
131 if (fd > 0) {
132 return OHOS_TEMP_FAILURE_RETRY(write(fd, buf, len));
133 }
134 return 0;
135 }
136 } // namespace HiviewDFX
137 } // namespace OHOS
138