1 /*
2 * Copyright (C) 2023 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 "dmesg_catcher.h"
16
17 #include <string>
18 #include <sys/klog.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23
24 #include "hiview_logger.h"
25 #include "log_catcher_utils.h"
26 #include "common_utils.h"
27 #include "file_util.h"
28 #include "time_util.h"
29 #include "securec.h"
30 namespace OHOS {
31 namespace HiviewDFX {
32 DEFINE_LOG_LABEL(0xD002D01, "EventLogger-DmesgCatcher");
33 namespace {
34 constexpr int SYSLOG_ACTION_READ_ALL = 3;
35 constexpr int SYSLOG_ACTION_SIZE_BUFFER = 10;
36 constexpr mode_t DEFAULT_LOG_FILE_MODE = 0644;
37 static constexpr const char* const FULL_DIR = "/data/log/eventlog/";
38 }
DmesgCatcher()39 DmesgCatcher::DmesgCatcher() : EventLogCatcher()
40 {
41 event_ = nullptr;
42 name_ = "DmesgCatcher";
43 }
44
Initialize(const std::string& packageNam __UNUSED, int isWriteNewFile __UNUSED, int intParam)45 bool DmesgCatcher::Initialize(const std::string& packageNam __UNUSED,
46 int isWriteNewFile __UNUSED, int intParam)
47 {
48 isWriteNewFile_ = isWriteNewFile;
49 needWriteSysrq_ = intParam;
50 return true;
51 }
52
Init(std::shared_ptr<SysEvent> event)53 bool DmesgCatcher::Init(std::shared_ptr<SysEvent> event)
54 {
55 event_ = event;
56 return true;
57 }
58
DumpDmesgLog(int fd)59 bool DmesgCatcher::DumpDmesgLog(int fd)
60 {
61 if (fd < 0) {
62 return false;
63 }
64 int size = klogctl(SYSLOG_ACTION_SIZE_BUFFER, 0, 0);
65 if (size <= 0) {
66 return false;
67 }
68 char *data = (char *)malloc(size + 1);
69 if (data == nullptr) {
70 return false;
71 }
72
73 memset_s(data, size + 1, 0, size + 1);
74 int readSize = klogctl(SYSLOG_ACTION_READ_ALL, data, size);
75 if (readSize < 0) {
76 free(data);
77 return false;
78 }
79 bool res = FileUtil::SaveStringToFd(fd, data);
80 free(data);
81 return res;
82 }
83
WriteSysrq()84 bool DmesgCatcher::WriteSysrq()
85 {
86 FILE* file = fopen("/proc/sysrq-trigger", "w");
87 if (file == nullptr) {
88 HIVIEW_LOGE("Can't read sysrq,errno: %{public}d", errno);
89 return false;
90 }
91 fwrite("w", 1, 1, file);
92 fflush(file);
93
94 fwrite("l", 1, 1, file);
95 sleep(1);
96 fclose(file);
97 return true;
98 }
99
DmesgSaveTofile()100 std::string DmesgCatcher::DmesgSaveTofile()
101 {
102 auto logTime = TimeUtil::GetMilliseconds() / TimeUtil::SEC_TO_MILLISEC;
103 std::string sysrqTime = TimeUtil::TimestampFormatToDate(logTime, "%Y%m%d%H%M%S");
104 std::string fullPath = std::string(FULL_DIR) + "sysrq-" + sysrqTime + ".log";
105 if (FileUtil::FileExists(fullPath)) {
106 HIVIEW_LOGW("filename: %{public}s is existed, direct use.", fullPath.c_str());
107 return fullPath;
108 }
109
110 auto fd = open(fullPath.c_str(), O_CREAT | O_WRONLY | O_TRUNC, DEFAULT_LOG_FILE_MODE);
111 if (fd < 0) {
112 HIVIEW_LOGI("Fail to create %s.", fullPath.c_str());
113 return "";
114 }
115 bool dumpRet = DumpDmesgLog(fd);
116 close(fd);
117
118 if (!dumpRet) {
119 return "";
120 }
121 if (event_ != nullptr) {
122 event_->SetEventValue("SYSRQ_TIME", sysrqTime);
123 }
124 return fullPath;
125 }
126
Catch(int fd, int jsonFd)127 int DmesgCatcher::Catch(int fd, int jsonFd)
128 {
129 if (needWriteSysrq_ && !WriteSysrq()) {
130 return 0;
131 }
132
133 description_ = needWriteSysrq_ ? "\nSysrqCatcher -- " : "DmesgCatcher -- ";
134
135 auto originSize = GetFdSize(fd);
136 if (isWriteNewFile_) {
137 std::string fullPath = DmesgSaveTofile();
138 if (fullPath.empty()) {
139 return 0;
140 }
141 description_ += "fullPath:" + fullPath + "\n";
142 FileUtil::SaveStringToFd(fd, description_);
143 } else {
144 description_ += "\n";
145 FileUtil::SaveStringToFd(fd, description_);
146 DumpDmesgLog(fd);
147 }
148 logSize_ = GetFdSize(fd) - originSize;
149 return logSize_;
150 }
151 } // namespace HiviewDFX
152 } // namespace OHOS
153