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" 30namespace OHOS { 31namespace HiviewDFX { 32DEFINE_LOG_LABEL(0xD002D01, "EventLogger-DmesgCatcher"); 33namespace { 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} 39DmesgCatcher::DmesgCatcher() : EventLogCatcher() 40{ 41 event_ = nullptr; 42 name_ = "DmesgCatcher"; 43} 44 45bool 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 53bool DmesgCatcher::Init(std::shared_ptr<SysEvent> event) 54{ 55 event_ = event; 56 return true; 57} 58 59bool 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 84bool 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 100std::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 127int 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