• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "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 }
DmesgCatcher()38 DmesgCatcher::DmesgCatcher() : EventLogCatcher()
39 {
40     event_ = nullptr;
41     name_ = "DmesgCatcher";
42 }
43 
Initialize(const std::string & packageNam __UNUSED,int isWriteNewFile __UNUSED,int intParam)44 bool DmesgCatcher::Initialize(const std::string& packageNam  __UNUSED,
45     int isWriteNewFile  __UNUSED, int intParam)
46 {
47     isWriteNewFile_ = isWriteNewFile;
48     needWriteSysrq_ = intParam;
49     return true;
50 }
51 
Init(std::shared_ptr<SysEvent> event)52 bool DmesgCatcher::Init(std::shared_ptr<SysEvent> event)
53 {
54     event_ = event;
55     return true;
56 }
57 
DumpDmesgLog(int fd)58 bool DmesgCatcher::DumpDmesgLog(int fd)
59 {
60     if (fd < 0) {
61         return false;
62     }
63     int size = klogctl(SYSLOG_ACTION_SIZE_BUFFER, 0, 0);
64     if (size <= 0) {
65         return false;
66     }
67     char *data = (char *)malloc(size + 1);
68     if (data == nullptr) {
69         return false;
70     }
71 
72     memset_s(data, size + 1, 0, size + 1);
73     int readSize = klogctl(SYSLOG_ACTION_READ_ALL, data, size);
74     if (readSize < 0) {
75         free(data);
76         return false;
77     }
78     bool res = FileUtil::SaveStringToFd(fd, data);
79     free(data);
80     return res;
81 }
82 
WriteSysrq()83 bool DmesgCatcher::WriteSysrq()
84 {
85     FILE* file = fopen("/proc/sysrq-trigger", "w");
86     if (file == nullptr) {
87         HIVIEW_LOGE("Can't read sysrq,errno: %{public}d", errno);
88         return false;
89     }
90     fwrite("w", 1, 1, file);
91     fflush(file);
92 
93     fwrite("l", 1, 1, file);
94     sleep(1);
95     fclose(file);
96     return true;
97 }
98 
DmesgSaveTofile()99 std::string DmesgCatcher::DmesgSaveTofile()
100 {
101     auto logTime = TimeUtil::GetMilliseconds() / TimeUtil::SEC_TO_MILLISEC;
102     std::string sysrqTime = TimeUtil::TimestampFormatToDate(logTime, "%Y%m%d%H%M%S");
103     std::string fullPath = FULL_DIR + "sysrq-" + sysrqTime + ".log";
104 
105     if (FileUtil::FileExists(fullPath)) {
106         HIVIEW_LOGW("filename: %{public}s is existed, direct use.", fullPath.c_str());
107         return fullPath;
108     }
109     std::string realPath;
110     if (!FileUtil::PathToRealPath(fullPath,realPath)) {
111         HIVIEW_LOGI("Fail to verify realpath %s.", fullPath.c_str());
112         return "";
113     }
114     auto fd = open(realPath.c_str(), O_CREAT | O_WRONLY | O_TRUNC, DEFAULT_LOG_FILE_MODE);
115     if (fd < 0) {
116         HIVIEW_LOGI("Fail to create %s.", realPath.c_str());
117         return "";
118     }
119     bool dumpRet = DumpDmesgLog(fd);
120     close(fd);
121 
122     if (!dumpRet) {
123         return "";
124     }
125     if (event_ != nullptr) {
126         event_->SetEventValue("SYSRQ_TIME", sysrqTime);
127     }
128     return realPath;
129 }
130 
Catch(int fd)131 int DmesgCatcher::Catch(int fd)
132 {
133     if (needWriteSysrq_ && !WriteSysrq()) {
134         return 0;
135     }
136 
137     description_ = needWriteSysrq_ ? "\nSysrqCatcher -- " : "DmesgCatcher -- ";
138 
139     auto originSize = GetFdSize(fd);
140     if (isWriteNewFile_) {
141         std::string fullPath = DmesgSaveTofile();
142         if (fullPath.empty()) {
143             return 0;
144         }
145         description_ += "fullPath:" + fullPath + "\n";
146         FileUtil::SaveStringToFd(fd, description_);
147     } else {
148         description_ += "\n";
149         FileUtil::SaveStringToFd(fd, description_);
150         DumpDmesgLog(fd);
151     }
152     logSize_ = GetFdSize(fd) - originSize;
153     return logSize_;
154 }
155 } // namespace HiviewDFX
156 } // namespace OHOS
157