1 /*
2  * Copyright (c) 2021 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 "log/log.h"
16 #include <chrono>
17 #include <cstdarg>
18 #include <memory>
19 #include <unordered_map>
20 #include <vector>
21 #include <sys/time.h>
22 #include <unistd.h>
23 #include <mutex>
24 #ifndef DIFF_PATCH_SDK
25 #include "hilog_base/log_base.h"
26 #include "vsnprintf_s_p.h"
27 #endif
28 #include "securec.h"
29 
30 namespace Updater {
31 static std::ofstream g_updaterLog;
32 static std::mutex g_updaterLogLock;
33 static std::ofstream g_updaterStage;
34 static std::ofstream g_errorCode;
35 static std::ofstream g_nullStream;
36 static std::string g_logTag;
37 static int g_logLevel = INFO;
38 #ifndef DIFF_PATCH_SDK
39 static constexpr unsigned int UPDATER_DOMAIN = 0XD002E01;
40 #endif
41 
InitUpdaterLogger(const std::string & tag,const std::string & logFile,const std::string & stageFile,const std::string & errorCodeFile)42 void InitUpdaterLogger(const std::string &tag, const std::string &logFile, const std::string &stageFile,
43     const std::string &errorCodeFile)
44 {
45     g_logTag = tag;
46     g_updaterLog.open(logFile.c_str(), std::ios::app | std::ios::out);
47     g_updaterStage.open(stageFile.c_str(), std::ios::app | std::ios::out);
48     g_errorCode.open(errorCodeFile.c_str(), std::ios::app | std::ios::out);
49 }
50 
~UpdaterLogger()51 UpdaterLogger::~UpdaterLogger()
52 {
53     std::string str = oss_.str();
54     if (g_logLevel > level_) {
55         return;
56     }
57     pid_t tid = 0;
58 #ifndef DIFF_PATCH_SDK
59     HiLogBasePrint(LOG_CORE, (LogLevel)level_, UPDATER_DOMAIN, g_logTag.c_str(), "%{public}s", str.c_str());
60     tid = gettid();
61 #endif
62     oss_.str("");
63     oss_ << std::endl << std::flush;
64     if (g_updaterLog.is_open()) {
65         std::lock_guard<std::mutex> lock(g_updaterLogLock);
66         g_updaterLog << realTime_ <<  " " << g_logTag << " " <<  tid << " "
67             << logLevelMap_[level_] << " " << str << std::endl << std::flush;
68     }
69 }
70 
~StageLogger()71 StageLogger::~StageLogger()
72 {
73     if (g_updaterStage.is_open()) {
74         g_updaterStage << std::endl << std::flush;
75     } else {
76         std::cout << std::endl << std::flush;
77     }
78 }
79 
SetLogLevel(int level)80 void SetLogLevel(int level)
81 {
82     g_logLevel = level;
83 }
84 
GetFormatTime(char time[],int size)85 void GetFormatTime(char time[], int size)
86 {
87 #ifndef DIFF_PATCH_SDK
88     struct timeval tv {};
89     struct tm tm {};
90 
91     gettimeofday(&tv, nullptr);
92     localtime_r(&tv.tv_sec, &tm);
93     snprintf_s(time, size, size - 1, "%02d-%02d %02d:%02d:%02d.%03d",
94         tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
95         static_cast<int>(tv.tv_usec / 1000)); // need div 1000
96 #endif
97 }
98 
OutputUpdaterLog(const std::string & path,int line)99 std::ostream& UpdaterLogger::OutputUpdaterLog(const std::string &path, int line)
100 {
101     GetFormatTime(realTime_, sizeof(realTime_));
102     if (g_logLevel <= level_) {
103         return oss_ << path << " " << line << " : ";
104     }
105     return g_nullStream;
106 }
107 
OutputUpdaterStage()108 std::ostream& StageLogger::OutputUpdaterStage()
109 {
110     std::unordered_map<int, std::string> updaterStageMap = {
111         { UPDATE_STAGE_BEGIN, "BEGIN" },
112         { UPDATE_STAGE_SUCCESS, "SUCCESS" },
113         { UPDATE_STAGE_FAIL, "FAIL" },
114         { UPDATE_STAGE_OUT, "OUT" }
115     };
116     char realTime[MAX_TIME_SIZE] = {0};
117     GetFormatTime(realTime, sizeof(realTime));
118 
119     if (g_updaterLog.is_open()) {
120         if (stage_ == UPDATE_STAGE_OUT) {
121             return g_updaterStage << realTime << "  " << g_logTag << " ";
122         }
123         return g_updaterStage << realTime << "  " << g_logTag << " status is : " <<
124             updaterStageMap[stage_] << ", stage is ";
125     }
126     return std::cout;
127 }
128 
Logger(int level,const char * fileName,int32_t line,const char * format,...)129 void Logger(int level, const char* fileName, int32_t line, const char* format, ...)
130 {
131     std::vector<char> buff(1024); // 1024 : max length of buff
132     va_list list;
133     va_start(list, format);
134     int size = vsnprintf_s(reinterpret_cast<char*>(buff.data()), buff.capacity(), buff.capacity(), format, list);
135     va_end(list);
136     if (size < EOK) {
137         UpdaterLogger(level).OutputUpdaterLog(fileName, line) << "vsnprintf_s failed";
138         return;
139     }
140     std::string str(buff.data(), size);
141     UpdaterLogger(level).OutputUpdaterLog(fileName, line) << str;
142 }
143 
144 #ifndef DIFF_PATCH_SDK
145 // used for external module to adapt %{private|public} format log to updater log
UpdaterHiLogger(int level,const char * fileName,int32_t line,const char * format,...)146 void UpdaterHiLogger(int level, const char* fileName, int32_t line, const char* format, ...)
147 {
148     char buf[MAX_LOG_LEN] = {0};
149     va_list list;
150     va_start(list, format);
151     int size = vsnprintfp_s(buf, MAX_LOG_LEN, MAX_LOG_LEN - 1, true, format, list);
152     va_end(list);
153     if (size < EOK) {
154         UpdaterLogger(level).OutputUpdaterLog(fileName, line) << "vsnprintfp_s failed " << size;
155     } else {
156         UpdaterLogger(level).OutputUpdaterLog(fileName, line) << std::string(buf, size);
157     }
158 }
159 #endif
160 
OutputErrorCode(const std::string & path,int line,UpdaterErrorCode code)161 std::ostream& ErrorCode::OutputErrorCode(const std::string &path, int line, UpdaterErrorCode code)
162 {
163     char realTime[MAX_TIME_SIZE] = {0};
164     GetFormatTime(realTime, sizeof(realTime));
165     if (g_errorCode.is_open()) {
166         return g_errorCode << realTime <<  "  " << path << " " << line << " , error code is : " << code << std::endl;
167     }
168     return std::cout;
169 }
170 } // Updater
171