1020a203aSopenharmony_ci/* 2020a203aSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4020a203aSopenharmony_ci * you may not use this file except in compliance with the License. 5020a203aSopenharmony_ci * You may obtain a copy of the License at 6020a203aSopenharmony_ci * 7020a203aSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8020a203aSopenharmony_ci * 9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12020a203aSopenharmony_ci * See the License for the specific language governing permissions and 13020a203aSopenharmony_ci * limitations under the License. 14020a203aSopenharmony_ci */ 15020a203aSopenharmony_ci#include "dmesg_catcher.h" 16020a203aSopenharmony_ci 17020a203aSopenharmony_ci#include <string> 18020a203aSopenharmony_ci#include <sys/klog.h> 19020a203aSopenharmony_ci#include <unistd.h> 20020a203aSopenharmony_ci#include <fcntl.h> 21020a203aSopenharmony_ci#include <sys/stat.h> 22020a203aSopenharmony_ci#include <sys/types.h> 23020a203aSopenharmony_ci 24020a203aSopenharmony_ci#include "hiview_logger.h" 25020a203aSopenharmony_ci#include "log_catcher_utils.h" 26020a203aSopenharmony_ci#include "common_utils.h" 27020a203aSopenharmony_ci#include "file_util.h" 28020a203aSopenharmony_ci#include "time_util.h" 29020a203aSopenharmony_ci#include "securec.h" 30020a203aSopenharmony_cinamespace OHOS { 31020a203aSopenharmony_cinamespace HiviewDFX { 32020a203aSopenharmony_ciDEFINE_LOG_LABEL(0xD002D01, "EventLogger-DmesgCatcher"); 33020a203aSopenharmony_cinamespace { 34020a203aSopenharmony_ci constexpr int SYSLOG_ACTION_READ_ALL = 3; 35020a203aSopenharmony_ci constexpr int SYSLOG_ACTION_SIZE_BUFFER = 10; 36020a203aSopenharmony_ci constexpr mode_t DEFAULT_LOG_FILE_MODE = 0644; 37020a203aSopenharmony_ci static constexpr const char* const FULL_DIR = "/data/log/eventlog/"; 38020a203aSopenharmony_ci} 39020a203aSopenharmony_ciDmesgCatcher::DmesgCatcher() : EventLogCatcher() 40020a203aSopenharmony_ci{ 41020a203aSopenharmony_ci event_ = nullptr; 42020a203aSopenharmony_ci name_ = "DmesgCatcher"; 43020a203aSopenharmony_ci} 44020a203aSopenharmony_ci 45020a203aSopenharmony_cibool DmesgCatcher::Initialize(const std::string& packageNam __UNUSED, 46020a203aSopenharmony_ci int isWriteNewFile __UNUSED, int intParam) 47020a203aSopenharmony_ci{ 48020a203aSopenharmony_ci isWriteNewFile_ = isWriteNewFile; 49020a203aSopenharmony_ci needWriteSysrq_ = intParam; 50020a203aSopenharmony_ci return true; 51020a203aSopenharmony_ci} 52020a203aSopenharmony_ci 53020a203aSopenharmony_cibool DmesgCatcher::Init(std::shared_ptr<SysEvent> event) 54020a203aSopenharmony_ci{ 55020a203aSopenharmony_ci event_ = event; 56020a203aSopenharmony_ci return true; 57020a203aSopenharmony_ci} 58020a203aSopenharmony_ci 59020a203aSopenharmony_cibool DmesgCatcher::DumpDmesgLog(int fd) 60020a203aSopenharmony_ci{ 61020a203aSopenharmony_ci if (fd < 0) { 62020a203aSopenharmony_ci return false; 63020a203aSopenharmony_ci } 64020a203aSopenharmony_ci int size = klogctl(SYSLOG_ACTION_SIZE_BUFFER, 0, 0); 65020a203aSopenharmony_ci if (size <= 0) { 66020a203aSopenharmony_ci return false; 67020a203aSopenharmony_ci } 68020a203aSopenharmony_ci char *data = (char *)malloc(size + 1); 69020a203aSopenharmony_ci if (data == nullptr) { 70020a203aSopenharmony_ci return false; 71020a203aSopenharmony_ci } 72020a203aSopenharmony_ci 73020a203aSopenharmony_ci memset_s(data, size + 1, 0, size + 1); 74020a203aSopenharmony_ci int readSize = klogctl(SYSLOG_ACTION_READ_ALL, data, size); 75020a203aSopenharmony_ci if (readSize < 0) { 76020a203aSopenharmony_ci free(data); 77020a203aSopenharmony_ci return false; 78020a203aSopenharmony_ci } 79020a203aSopenharmony_ci bool res = FileUtil::SaveStringToFd(fd, data); 80020a203aSopenharmony_ci free(data); 81020a203aSopenharmony_ci return res; 82020a203aSopenharmony_ci} 83020a203aSopenharmony_ci 84020a203aSopenharmony_cibool DmesgCatcher::WriteSysrq() 85020a203aSopenharmony_ci{ 86020a203aSopenharmony_ci FILE* file = fopen("/proc/sysrq-trigger", "w"); 87020a203aSopenharmony_ci if (file == nullptr) { 88020a203aSopenharmony_ci HIVIEW_LOGE("Can't read sysrq,errno: %{public}d", errno); 89020a203aSopenharmony_ci return false; 90020a203aSopenharmony_ci } 91020a203aSopenharmony_ci fwrite("w", 1, 1, file); 92020a203aSopenharmony_ci fflush(file); 93020a203aSopenharmony_ci 94020a203aSopenharmony_ci fwrite("l", 1, 1, file); 95020a203aSopenharmony_ci sleep(1); 96020a203aSopenharmony_ci fclose(file); 97020a203aSopenharmony_ci return true; 98020a203aSopenharmony_ci} 99020a203aSopenharmony_ci 100020a203aSopenharmony_cistd::string DmesgCatcher::DmesgSaveTofile() 101020a203aSopenharmony_ci{ 102020a203aSopenharmony_ci auto logTime = TimeUtil::GetMilliseconds() / TimeUtil::SEC_TO_MILLISEC; 103020a203aSopenharmony_ci std::string sysrqTime = TimeUtil::TimestampFormatToDate(logTime, "%Y%m%d%H%M%S"); 104020a203aSopenharmony_ci std::string fullPath = std::string(FULL_DIR) + "sysrq-" + sysrqTime + ".log"; 105020a203aSopenharmony_ci if (FileUtil::FileExists(fullPath)) { 106020a203aSopenharmony_ci HIVIEW_LOGW("filename: %{public}s is existed, direct use.", fullPath.c_str()); 107020a203aSopenharmony_ci return fullPath; 108020a203aSopenharmony_ci } 109020a203aSopenharmony_ci 110020a203aSopenharmony_ci auto fd = open(fullPath.c_str(), O_CREAT | O_WRONLY | O_TRUNC, DEFAULT_LOG_FILE_MODE); 111020a203aSopenharmony_ci if (fd < 0) { 112020a203aSopenharmony_ci HIVIEW_LOGI("Fail to create %s.", fullPath.c_str()); 113020a203aSopenharmony_ci return ""; 114020a203aSopenharmony_ci } 115020a203aSopenharmony_ci bool dumpRet = DumpDmesgLog(fd); 116020a203aSopenharmony_ci close(fd); 117020a203aSopenharmony_ci 118020a203aSopenharmony_ci if (!dumpRet) { 119020a203aSopenharmony_ci return ""; 120020a203aSopenharmony_ci } 121020a203aSopenharmony_ci if (event_ != nullptr) { 122020a203aSopenharmony_ci event_->SetEventValue("SYSRQ_TIME", sysrqTime); 123020a203aSopenharmony_ci } 124020a203aSopenharmony_ci return fullPath; 125020a203aSopenharmony_ci} 126020a203aSopenharmony_ci 127020a203aSopenharmony_ciint DmesgCatcher::Catch(int fd, int jsonFd) 128020a203aSopenharmony_ci{ 129020a203aSopenharmony_ci if (needWriteSysrq_ && !WriteSysrq()) { 130020a203aSopenharmony_ci return 0; 131020a203aSopenharmony_ci } 132020a203aSopenharmony_ci 133020a203aSopenharmony_ci description_ = needWriteSysrq_ ? "\nSysrqCatcher -- " : "DmesgCatcher -- "; 134020a203aSopenharmony_ci 135020a203aSopenharmony_ci auto originSize = GetFdSize(fd); 136020a203aSopenharmony_ci if (isWriteNewFile_) { 137020a203aSopenharmony_ci std::string fullPath = DmesgSaveTofile(); 138020a203aSopenharmony_ci if (fullPath.empty()) { 139020a203aSopenharmony_ci return 0; 140020a203aSopenharmony_ci } 141020a203aSopenharmony_ci description_ += "fullPath:" + fullPath + "\n"; 142020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, description_); 143020a203aSopenharmony_ci } else { 144020a203aSopenharmony_ci description_ += "\n"; 145020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, description_); 146020a203aSopenharmony_ci DumpDmesgLog(fd); 147020a203aSopenharmony_ci } 148020a203aSopenharmony_ci logSize_ = GetFdSize(fd) - originSize; 149020a203aSopenharmony_ci return logSize_; 150020a203aSopenharmony_ci} 151020a203aSopenharmony_ci} // namespace HiviewDFX 152020a203aSopenharmony_ci} // namespace OHOS 153