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