1cc290419Sopenharmony_ci/* 2cc290419Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd. 3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License. 5cc290419Sopenharmony_ci * You may obtain a copy of the License at 6cc290419Sopenharmony_ci * 7cc290419Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8cc290419Sopenharmony_ci * 9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and 13cc290419Sopenharmony_ci * limitations under the License. 14cc290419Sopenharmony_ci */ 15cc290419Sopenharmony_ci#include "base.h" 16cc290419Sopenharmony_ci#include <algorithm> 17cc290419Sopenharmony_ci#include <chrono> 18cc290419Sopenharmony_ci#include <cstdio> 19cc290419Sopenharmony_ci#include <cstring> 20cc290419Sopenharmony_ci#include <dirent.h> 21cc290419Sopenharmony_ci#include <iomanip> 22cc290419Sopenharmony_ci#include <openssl/bio.h> 23cc290419Sopenharmony_ci#include <openssl/buffer.h> 24cc290419Sopenharmony_ci#include <openssl/evp.h> 25cc290419Sopenharmony_ci#include <openssl/md5.h> 26cc290419Sopenharmony_ci#include <random> 27cc290419Sopenharmony_ci#include <sstream> 28cc290419Sopenharmony_ci#include <sys/stat.h> 29cc290419Sopenharmony_ci#include <thread> 30cc290419Sopenharmony_ci#include <vector> 31cc290419Sopenharmony_ci#ifdef HDC_HILOG 32cc290419Sopenharmony_ci#include "hilog/log.h" 33cc290419Sopenharmony_ci#endif 34cc290419Sopenharmony_ci#ifdef _WIN32 35cc290419Sopenharmony_ci#include <windows.h> 36cc290419Sopenharmony_ci#include <codecvt> 37cc290419Sopenharmony_ci#include <wchar.h> 38cc290419Sopenharmony_ci#include <wincrypt.h> 39cc290419Sopenharmony_ci#else 40cc290419Sopenharmony_ci#include <sys/wait.h> 41cc290419Sopenharmony_ci#endif 42cc290419Sopenharmony_ci#include <fstream> 43cc290419Sopenharmony_ciusing namespace std::chrono; 44cc290419Sopenharmony_ci 45cc290419Sopenharmony_cinamespace Hdc { 46cc290419Sopenharmony_cinamespace Base { 47cc290419Sopenharmony_ci constexpr int DEF_FILE_PERMISSION = 0750; 48cc290419Sopenharmony_ci#ifndef _WIN32 49cc290419Sopenharmony_ci sigset_t g_blockList; 50cc290419Sopenharmony_ci#endif 51cc290419Sopenharmony_ci uint8_t GetLogLevel() 52cc290419Sopenharmony_ci { 53cc290419Sopenharmony_ci return g_logLevel; 54cc290419Sopenharmony_ci } 55cc290419Sopenharmony_ci#ifndef HDC_HILOG 56cc290419Sopenharmony_ci std::atomic<bool> g_logCache = true; 57cc290419Sopenharmony_ci#endif 58cc290419Sopenharmony_ci uint8_t g_logLevel = LOG_DEBUG; // tmp set,now debugmode.LOG_OFF when release;; 59cc290419Sopenharmony_ci void SetLogLevel(const uint8_t logLevel) 60cc290419Sopenharmony_ci { 61cc290419Sopenharmony_ci g_logLevel = logLevel; 62cc290419Sopenharmony_ci } 63cc290419Sopenharmony_ci 64cc290419Sopenharmony_ci uint8_t GetLogLevelByEnv() 65cc290419Sopenharmony_ci { 66cc290419Sopenharmony_ci char *env = getenv(ENV_SERVER_LOG.c_str()); 67cc290419Sopenharmony_ci if (!env) { 68cc290419Sopenharmony_ci return GetLogLevel(); 69cc290419Sopenharmony_ci } 70cc290419Sopenharmony_ci size_t len = strlen(env); 71cc290419Sopenharmony_ci 72cc290419Sopenharmony_ci size_t maxLen = 1; 73cc290419Sopenharmony_ci if (len > maxLen) { 74cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "OHOS_HDC_LOG_LEVEL %s is not in (0, 6] range", env); 75cc290419Sopenharmony_ci return GetLogLevel(); 76cc290419Sopenharmony_ci } 77cc290419Sopenharmony_ci 78cc290419Sopenharmony_ci for (size_t i = 0; i < len; i++) { 79cc290419Sopenharmony_ci if (isdigit(env[i]) == 0) { 80cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "OHOS_HDC_LOG_LEVEL %s is not digit", env); 81cc290419Sopenharmony_ci return GetLogLevel(); 82cc290419Sopenharmony_ci } 83cc290419Sopenharmony_ci } 84cc290419Sopenharmony_ci 85cc290419Sopenharmony_ci uint8_t logLevel = static_cast<uint8_t>(atoi(env)); 86cc290419Sopenharmony_ci if (logLevel < 0 || logLevel > LOG_LAST) { 87cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "OHOS_HDC_LOG_LEVEL %d is not in (0, 6] range", logLevel); 88cc290419Sopenharmony_ci } else { 89cc290419Sopenharmony_ci return logLevel; 90cc290419Sopenharmony_ci } 91cc290419Sopenharmony_ci 92cc290419Sopenharmony_ci return GetLogLevel(); 93cc290419Sopenharmony_ci } 94cc290419Sopenharmony_ci 95cc290419Sopenharmony_ci// Commenting the code will optimize and tune all log codes, and the compilation volume will be greatly reduced 96cc290419Sopenharmony_ci#define ENABLE_DEBUGLOG 97cc290419Sopenharmony_ci#ifdef ENABLE_DEBUGLOG 98cc290419Sopenharmony_ci void GetLogDebugFunctionName(string &debugInfo, int line, string &threadIdString) 99cc290419Sopenharmony_ci { 100cc290419Sopenharmony_ci string tmpString = GetFileNameAny(debugInfo); 101cc290419Sopenharmony_ci debugInfo = StringFormat("%s:%d", tmpString.c_str(), line); 102cc290419Sopenharmony_ci if (g_logLevel < LOG_DEBUG) { 103cc290419Sopenharmony_ci debugInfo = ""; 104cc290419Sopenharmony_ci threadIdString = ""; 105cc290419Sopenharmony_ci } else { 106cc290419Sopenharmony_ci debugInfo = "[" + debugInfo + "]"; 107cc290419Sopenharmony_ci threadIdString = StringFormat("[%x]", std::hash<std::thread::id> {}(std::this_thread::get_id())); 108cc290419Sopenharmony_ci } 109cc290419Sopenharmony_ci } 110cc290419Sopenharmony_ci 111cc290419Sopenharmony_ci void GetLogLevelAndTime(uint8_t logLevel, string &logLevelString, string &timeString) 112cc290419Sopenharmony_ci { 113cc290419Sopenharmony_ci system_clock::time_point timeNow = system_clock::now(); // now time 114cc290419Sopenharmony_ci system_clock::duration sinceUnix0 = timeNow.time_since_epoch(); // since 1970 115cc290419Sopenharmony_ci time_t sSinceUnix0 = duration_cast<seconds>(sinceUnix0).count(); 116cc290419Sopenharmony_ci std::tm *tim = std::localtime(&sSinceUnix0); 117cc290419Sopenharmony_ci switch (logLevel) { 118cc290419Sopenharmony_ci case LOG_FATAL: 119cc290419Sopenharmony_ci logLevelString = "F"; 120cc290419Sopenharmony_ci break; 121cc290419Sopenharmony_ci case LOG_INFO: 122cc290419Sopenharmony_ci logLevelString = "I"; 123cc290419Sopenharmony_ci break; 124cc290419Sopenharmony_ci case LOG_WARN: 125cc290419Sopenharmony_ci logLevelString = "W"; 126cc290419Sopenharmony_ci break; 127cc290419Sopenharmony_ci case LOG_DEBUG: // will reduce performance 128cc290419Sopenharmony_ci logLevelString = "D"; 129cc290419Sopenharmony_ci break; 130cc290419Sopenharmony_ci default: // all, just more IO/Memory information 131cc290419Sopenharmony_ci logLevelString = "A"; 132cc290419Sopenharmony_ci break; 133cc290419Sopenharmony_ci } 134cc290419Sopenharmony_ci string msTimeSurplus; 135cc290419Sopenharmony_ci if (g_logLevel >= LOG_DEBUG) { 136cc290419Sopenharmony_ci const auto sSinceUnix0Rest = duration_cast<milliseconds>(sinceUnix0).count() % TIME_BASE; 137cc290419Sopenharmony_ci msTimeSurplus = StringFormat(".%03llu", sSinceUnix0Rest); 138cc290419Sopenharmony_ci } 139cc290419Sopenharmony_ci timeString = msTimeSurplus; 140cc290419Sopenharmony_ci if (tim != nullptr) { 141cc290419Sopenharmony_ci char buffer[TIME_BUF_SIZE]; 142cc290419Sopenharmony_ci (void)strftime(buffer, TIME_BUF_SIZE, "%Y-%m-%d %H:%M:%S", tim); 143cc290419Sopenharmony_ci timeString = StringFormat("%s%s", buffer, msTimeSurplus.c_str()); 144cc290419Sopenharmony_ci } 145cc290419Sopenharmony_ci } 146cc290419Sopenharmony_ci 147cc290419Sopenharmony_ci#ifndef HDC_HILOG 148cc290419Sopenharmony_ci void LogToPath(const char *path, const char *str) 149cc290419Sopenharmony_ci { 150cc290419Sopenharmony_ci // logfile, not thread-safe 151cc290419Sopenharmony_ci#ifdef HDC_DEBUG_UART 152cc290419Sopenharmony_ci // make a log path print. 153cc290419Sopenharmony_ci static std::once_flag firstLog; 154cc290419Sopenharmony_ci std::call_once(firstLog, [&]() { printf("log at %s\n", path); }); 155cc290419Sopenharmony_ci // better than open log file every time. 156cc290419Sopenharmony_ci static std::unique_ptr<FILE, decltype(&fclose)> file(fopen(path, "w"), &fclose); 157cc290419Sopenharmony_ci FILE *fp = file.get(); 158cc290419Sopenharmony_ci if (fp == nullptr) { 159cc290419Sopenharmony_ci return; 160cc290419Sopenharmony_ci } 161cc290419Sopenharmony_ci if (fprintf(fp, "%s", str) > 0 && fflush(fp)) { 162cc290419Sopenharmony_ci // make ci happy 163cc290419Sopenharmony_ci } 164cc290419Sopenharmony_ci fclose(fp); 165cc290419Sopenharmony_ci#else 166cc290419Sopenharmony_ci int flags = UV_FS_O_RDWR | UV_FS_O_APPEND | UV_FS_O_CREAT; 167cc290419Sopenharmony_ci uv_fs_t req; 168cc290419Sopenharmony_ci int fd = uv_fs_open(nullptr, &req, path, flags, S_IWUSR | S_IRUSR, nullptr); 169cc290419Sopenharmony_ci if (fd < 0) { 170cc290419Sopenharmony_ci char buffer[BUF_SIZE_DEFAULT] = { 0 }; 171cc290419Sopenharmony_ci uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 172cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 173cc290419Sopenharmony_ci PrintMessage("LogToPath uv_fs_open %s error %s", path, buffer); 174cc290419Sopenharmony_ci return; 175cc290419Sopenharmony_ci } 176cc290419Sopenharmony_ci string text(str); 177cc290419Sopenharmony_ci uv_buf_t wbf = uv_buf_init((char *)str, text.size()); 178cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 179cc290419Sopenharmony_ci uv_fs_write(nullptr, &req, fd, &wbf, 1, -1, nullptr); 180cc290419Sopenharmony_ci uv_fs_close(nullptr, &req, fd, nullptr); 181cc290419Sopenharmony_ci#endif 182cc290419Sopenharmony_ci } 183cc290419Sopenharmony_ci 184cc290419Sopenharmony_ci void GetTimeString(string &timeString) 185cc290419Sopenharmony_ci { 186cc290419Sopenharmony_ci system_clock::time_point timeNow = system_clock::now(); 187cc290419Sopenharmony_ci system_clock::duration sinceUnix0 = timeNow.time_since_epoch(); // since 1970 188cc290419Sopenharmony_ci time_t sinceUnix0Time = duration_cast<seconds>(sinceUnix0).count(); 189cc290419Sopenharmony_ci std::tm *timeTm = std::localtime(&sinceUnix0Time); 190cc290419Sopenharmony_ci 191cc290419Sopenharmony_ci const auto sinceUnix0Rest = duration_cast<milliseconds>(sinceUnix0).count() % TIME_BASE; 192cc290419Sopenharmony_ci string msTimeSurplus = StringFormat("%03llu", sinceUnix0Rest); 193cc290419Sopenharmony_ci timeString = msTimeSurplus; 194cc290419Sopenharmony_ci if (timeTm != nullptr) { 195cc290419Sopenharmony_ci char buffer[TIME_BUF_SIZE] = {0}; 196cc290419Sopenharmony_ci if (strftime(buffer, TIME_BUF_SIZE, "%Y%m%d-%H%M%S", timeTm) > 0) { 197cc290419Sopenharmony_ci timeString = StringFormat("%s%s", buffer, msTimeSurplus.c_str()); 198cc290419Sopenharmony_ci } 199cc290419Sopenharmony_ci } 200cc290419Sopenharmony_ci } 201cc290419Sopenharmony_ci 202cc290419Sopenharmony_ci bool CompareLogFileName(const string &a, const string &b) 203cc290419Sopenharmony_ci { 204cc290419Sopenharmony_ci return strcmp(a.c_str(), b.c_str()) > 0; 205cc290419Sopenharmony_ci } 206cc290419Sopenharmony_ci 207cc290419Sopenharmony_ci bool CreateLogDir() 208cc290419Sopenharmony_ci { 209cc290419Sopenharmony_ci string errMsg; 210cc290419Sopenharmony_ci if (!TryCreateDirectory(GetLogDirName(), errMsg)) { 211cc290419Sopenharmony_ci // Warning: no log dir, so the log here can not save into the log file. 212cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "[E002102]Create hdc_logs directory failed, the logs could not be saved into files."); 213cc290419Sopenharmony_ci return false; 214cc290419Sopenharmony_ci } 215cc290419Sopenharmony_ci return true; 216cc290419Sopenharmony_ci } 217cc290419Sopenharmony_ci 218cc290419Sopenharmony_ci string GetCompressLogFileName(string fileName) 219cc290419Sopenharmony_ci { 220cc290419Sopenharmony_ci // example: hdc-20230228-123456789.log.tgz 221cc290419Sopenharmony_ci return fileName + LOG_FILE_COMPRESS_SUFFIX; 222cc290419Sopenharmony_ci } 223cc290419Sopenharmony_ci 224cc290419Sopenharmony_ci uint32_t GetLogOverCount(vector<string> files, uint64_t limitDirSize) 225cc290419Sopenharmony_ci { 226cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "GetLogDirSize, file size: %d", files.size()); 227cc290419Sopenharmony_ci if (files.size() == 0) { 228cc290419Sopenharmony_ci return 0; 229cc290419Sopenharmony_ci } 230cc290419Sopenharmony_ci uint64_t totalSize = 0; 231cc290419Sopenharmony_ci uint32_t overCount = 0; 232cc290419Sopenharmony_ci int value = -1; 233cc290419Sopenharmony_ci for (auto name : files) { 234cc290419Sopenharmony_ci uv_fs_t req; 235cc290419Sopenharmony_ci string last = GetLogDirName() + name; 236cc290419Sopenharmony_ci string utfName = UnicodeToUtf8(last.c_str(), false); 237cc290419Sopenharmony_ci value = uv_fs_stat(nullptr, &req, utfName.c_str(), nullptr); 238cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 239cc290419Sopenharmony_ci if (value != 0) { 240cc290419Sopenharmony_ci constexpr int bufSize = BUF_SIZE_DEFAULT; 241cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 242cc290419Sopenharmony_ci uv_strerror_r(value, buf, bufSize); 243cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 244cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "GetLogDirSize error file %s not exist %s", utfName.c_str(), buf); 245cc290419Sopenharmony_ci } 246cc290419Sopenharmony_ci if (req.result == 0) { 247cc290419Sopenharmony_ci totalSize += req.statbuf.st_size; 248cc290419Sopenharmony_ci } 249cc290419Sopenharmony_ci if (totalSize > limitDirSize) { 250cc290419Sopenharmony_ci overCount++; 251cc290419Sopenharmony_ci } 252cc290419Sopenharmony_ci } 253cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "overCount: %u", overCount); 254cc290419Sopenharmony_ci return overCount; 255cc290419Sopenharmony_ci } 256cc290419Sopenharmony_ci 257cc290419Sopenharmony_ci static void ThreadCompressLog(string bakName) 258cc290419Sopenharmony_ci { 259cc290419Sopenharmony_ci string bakPath = GetLogDirName() + bakName; 260cc290419Sopenharmony_ci if (bakName.empty()) { 261cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ThreadCompressLog file name empty"); 262cc290419Sopenharmony_ci return; 263cc290419Sopenharmony_ci } 264cc290419Sopenharmony_ci if ((access(bakPath.c_str(), F_OK) != 0) || !CompressLogFile(bakName)) { 265cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ThreadCompressLog file %s not exist", bakPath.c_str()); 266cc290419Sopenharmony_ci return; 267cc290419Sopenharmony_ci } 268cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "ThreadCompressLog file %s.tgz success", bakPath.c_str()); 269cc290419Sopenharmony_ci unlink(bakPath.c_str()); 270cc290419Sopenharmony_ci } 271cc290419Sopenharmony_ci 272cc290419Sopenharmony_ci#ifdef _WIN32 273cc290419Sopenharmony_ci bool CompressLogFile(string fileName) 274cc290419Sopenharmony_ci { 275cc290419Sopenharmony_ci bool retVal = false; 276cc290419Sopenharmony_ci string full = GetLogDirName() + fileName; 277cc290419Sopenharmony_ci if (access(full.c_str(), F_OK) != 0) { 278cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "CompressLogFile file %s not exist", full.c_str()); 279cc290419Sopenharmony_ci return retVal; 280cc290419Sopenharmony_ci } 281cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "compress log file, fileName: %s", fileName.c_str()); 282cc290419Sopenharmony_ci char currentDir[BUF_SIZE_DEFAULT]; 283cc290419Sopenharmony_ci getcwd(currentDir, sizeof(currentDir)); 284cc290419Sopenharmony_ci 285cc290419Sopenharmony_ci char buf[BUF_SIZE_SMALL] = ""; 286cc290419Sopenharmony_ci if (sprintf_s(buf, sizeof(buf), "tar czfp %s %s", GetCompressLogFileName(fileName).c_str(), 287cc290419Sopenharmony_ci fileName.c_str()) < 0) { 288cc290419Sopenharmony_ci return retVal; 289cc290419Sopenharmony_ci } 290cc290419Sopenharmony_ci chdir(GetLogDirName().c_str()); 291cc290419Sopenharmony_ci STARTUPINFO si; 292cc290419Sopenharmony_ci PROCESS_INFORMATION pi; 293cc290419Sopenharmony_ci ZeroMemory(&si, sizeof(si)); 294cc290419Sopenharmony_ci si.cb = sizeof(si); 295cc290419Sopenharmony_ci ZeroMemory(&pi, sizeof(pi)); 296cc290419Sopenharmony_ci if (!CreateProcess(GetTarBinFile().c_str(), buf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { 297cc290419Sopenharmony_ci DWORD errorCode = GetLastError(); 298cc290419Sopenharmony_ci LPVOID messageBuffer; 299cc290419Sopenharmony_ci FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 300cc290419Sopenharmony_ci NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&messageBuffer, 0, NULL); 301cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "compress log file failed, cmd: %s, error: %s", buf, (LPCTSTR)messageBuffer); 302cc290419Sopenharmony_ci LocalFree(messageBuffer); 303cc290419Sopenharmony_ci } else { 304cc290419Sopenharmony_ci DWORD waitResult = WaitForSingleObject(pi.hProcess, INFINITE); 305cc290419Sopenharmony_ci if (waitResult == WAIT_OBJECT_0) { 306cc290419Sopenharmony_ci retVal = true; 307cc290419Sopenharmony_ci } else if (waitResult == WAIT_TIMEOUT) { 308cc290419Sopenharmony_ci retVal = true; 309cc290419Sopenharmony_ci } 310cc290419Sopenharmony_ci CloseHandle(pi.hProcess); 311cc290419Sopenharmony_ci CloseHandle(pi.hThread); 312cc290419Sopenharmony_ci } 313cc290419Sopenharmony_ci chdir(currentDir); 314cc290419Sopenharmony_ci return retVal; 315cc290419Sopenharmony_ci } 316cc290419Sopenharmony_ci 317cc290419Sopenharmony_ci#else 318cc290419Sopenharmony_ci bool CompressLogFile(string fileName) 319cc290419Sopenharmony_ci { 320cc290419Sopenharmony_ci bool retVal = false; 321cc290419Sopenharmony_ci string full = GetLogDirName() + fileName; 322cc290419Sopenharmony_ci if (access(full.c_str(), F_OK) != 0) { 323cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "CompressLogFile file %s not exist", full.c_str()); 324cc290419Sopenharmony_ci return retVal; 325cc290419Sopenharmony_ci } 326cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "compress log file, fileName: %s", fileName.c_str()); 327cc290419Sopenharmony_ci char currentDir[BUF_SIZE_DEFAULT]; 328cc290419Sopenharmony_ci getcwd(currentDir, sizeof(currentDir)); 329cc290419Sopenharmony_ci pid_t pc = fork(); // create process 330cc290419Sopenharmony_ci chdir(GetLogDirName().c_str()); 331cc290419Sopenharmony_ci if (pc < 0) { 332cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "fork subprocess failed."); 333cc290419Sopenharmony_ci } else if (!pc) { 334cc290419Sopenharmony_ci if ((execlp(GetTarToolName().c_str(), GetTarToolName().c_str(), GetTarParams().c_str(), 335cc290419Sopenharmony_ci GetCompressLogFileName(fileName).c_str(), fileName.c_str(), nullptr)) == -1) { 336cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "CompressLogFile execlp failed."); 337cc290419Sopenharmony_ci } 338cc290419Sopenharmony_ci } else { 339cc290419Sopenharmony_ci int status; 340cc290419Sopenharmony_ci waitpid(pc, &status, 0); 341cc290419Sopenharmony_ci if (WIFEXITED(status)) { 342cc290419Sopenharmony_ci int exitCode = WEXITSTATUS(status); 343cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "subprocess exited with status %d", exitCode); 344cc290419Sopenharmony_ci retVal = true; 345cc290419Sopenharmony_ci } else { 346cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "compress log file failed, filename:%s, error: %s", 347cc290419Sopenharmony_ci fileName.c_str(), strerror(errno)); 348cc290419Sopenharmony_ci } 349cc290419Sopenharmony_ci } 350cc290419Sopenharmony_ci chdir(currentDir); 351cc290419Sopenharmony_ci return retVal; 352cc290419Sopenharmony_ci } 353cc290419Sopenharmony_ci#endif 354cc290419Sopenharmony_ci 355cc290419Sopenharmony_ci void CompressLogFiles() 356cc290419Sopenharmony_ci { 357cc290419Sopenharmony_ci vector<string> files = GetDirFileName(); 358cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "search log dir files, get files count: %d", files.size()); 359cc290419Sopenharmony_ci if (files.size() == 0) { 360cc290419Sopenharmony_ci return; 361cc290419Sopenharmony_ci } 362cc290419Sopenharmony_ci for (auto name : files) { 363cc290419Sopenharmony_ci if (name.find(LOG_FILE_NAME) != string::npos) { 364cc290419Sopenharmony_ci continue; 365cc290419Sopenharmony_ci } 366cc290419Sopenharmony_ci if (name.find(LOG_FILE_COMPRESS_SUFFIX) != string::npos) { 367cc290419Sopenharmony_ci continue; 368cc290419Sopenharmony_ci } 369cc290419Sopenharmony_ci if ((name.find(LOG_FILE_SUFFIX) != string::npos && CompressLogFile(name))) { 370cc290419Sopenharmony_ci string full = GetLogDirName() + name; 371cc290419Sopenharmony_ci unlink(full.c_str()); 372cc290419Sopenharmony_ci } 373cc290419Sopenharmony_ci } 374cc290419Sopenharmony_ci } 375cc290419Sopenharmony_ci 376cc290419Sopenharmony_ci uint16_t GetLogLimitByEnv() 377cc290419Sopenharmony_ci { 378cc290419Sopenharmony_ci char *env = getenv(ENV_SERVER_LOG_LIMIT.c_str()); 379cc290419Sopenharmony_ci size_t maxLen = 5; 380cc290419Sopenharmony_ci if (!env || strlen(env) > maxLen) { 381cc290419Sopenharmony_ci return MAX_LOG_FILE_COUNT; 382cc290419Sopenharmony_ci } 383cc290419Sopenharmony_ci int limitCount = atoi(env); 384cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "get log limit count from env: %d", limitCount); 385cc290419Sopenharmony_ci if (limitCount <= 0) { 386cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "invalid log limit count: %d", limitCount); 387cc290419Sopenharmony_ci return MAX_LOG_FILE_COUNT; 388cc290419Sopenharmony_ci } else { 389cc290419Sopenharmony_ci return static_cast<uint16_t>(limitCount); 390cc290419Sopenharmony_ci } 391cc290419Sopenharmony_ci } 392cc290419Sopenharmony_ci 393cc290419Sopenharmony_ci 394cc290419Sopenharmony_ci#ifdef _WIN32 395cc290419Sopenharmony_ci void RemoveOlderLogFilesOnWindows() 396cc290419Sopenharmony_ci { 397cc290419Sopenharmony_ci vector<string> files; 398cc290419Sopenharmony_ci WIN32_FIND_DATA findData; 399cc290419Sopenharmony_ci HANDLE hFind = FindFirstFile((GetLogDirName() + "/*").c_str(), &findData); 400cc290419Sopenharmony_ci if (hFind == INVALID_HANDLE_VALUE) { 401cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "Failed to open TEMP dir"); 402cc290419Sopenharmony_ci return; 403cc290419Sopenharmony_ci } 404cc290419Sopenharmony_ci 405cc290419Sopenharmony_ci do { 406cc290419Sopenharmony_ci if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { 407cc290419Sopenharmony_ci SetErrorMode(SEM_FAILCRITICALERRORS); 408cc290419Sopenharmony_ci if (strncmp(findData.cFileName, LOG_FILE_NAME_PREFIX.c_str(), LOG_FILE_NAME_PREFIX.size()) == 0) { 409cc290419Sopenharmony_ci files.push_back(findData.cFileName); 410cc290419Sopenharmony_ci } 411cc290419Sopenharmony_ci } 412cc290419Sopenharmony_ci } while (FindNextFile(hFind, &findData)); 413cc290419Sopenharmony_ci FindClose(hFind); 414cc290419Sopenharmony_ci 415cc290419Sopenharmony_ci if (files.size() <= MAX_LOG_FILE_COUNT) { 416cc290419Sopenharmony_ci return; 417cc290419Sopenharmony_ci } 418cc290419Sopenharmony_ci 419cc290419Sopenharmony_ci // Sort file names by time, with earlier ones coming first 420cc290419Sopenharmony_ci sort(files.begin(), files.end(), CompareLogFileName); 421cc290419Sopenharmony_ci 422cc290419Sopenharmony_ci uint16_t deleteCount = files.size() - MAX_LOG_FILE_COUNT; 423cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "will delete log file, count: %u", deleteCount); 424cc290419Sopenharmony_ci uint16_t count = 0; 425cc290419Sopenharmony_ci for (auto name : files) { 426cc290419Sopenharmony_ci if (count >= deleteCount) { 427cc290419Sopenharmony_ci break; 428cc290419Sopenharmony_ci } 429cc290419Sopenharmony_ci string deleteFile = GetLogDirName() + name; 430cc290419Sopenharmony_ci LPCTSTR lpFileName = TEXT(deleteFile.c_str()); 431cc290419Sopenharmony_ci BOOL ret = DeleteFile(lpFileName); 432cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "delete: %s ret:%d", deleteFile.c_str(), ret); 433cc290419Sopenharmony_ci count++; 434cc290419Sopenharmony_ci } 435cc290419Sopenharmony_ci } 436cc290419Sopenharmony_ci#endif 437cc290419Sopenharmony_ci 438cc290419Sopenharmony_ci vector<string> GetDirFileName() 439cc290419Sopenharmony_ci { 440cc290419Sopenharmony_ci vector<string> files; 441cc290419Sopenharmony_ci#ifdef _WIN32 442cc290419Sopenharmony_ci WIN32_FIND_DATA findData; 443cc290419Sopenharmony_ci HANDLE hFind = FindFirstFile((GetLogDirName() + "/*").c_str(), &findData); 444cc290419Sopenharmony_ci if (hFind == INVALID_HANDLE_VALUE) { 445cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "Failed to open log dir"); 446cc290419Sopenharmony_ci return; 447cc290419Sopenharmony_ci } 448cc290419Sopenharmony_ci 449cc290419Sopenharmony_ci do { 450cc290419Sopenharmony_ci if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { 451cc290419Sopenharmony_ci SetErrorMode(SEM_FAILCRITICALERRORS); 452cc290419Sopenharmony_ci if (strncmp(findData.cFileName, LOG_FILE_NAME_PREFIX.c_str(), LOG_FILE_NAME_PREFIX.size()) == 0) { 453cc290419Sopenharmony_ci files.push_back(findData.cFileName); 454cc290419Sopenharmony_ci } 455cc290419Sopenharmony_ci } 456cc290419Sopenharmony_ci } while (FindNextFile(hFind, &findData)); 457cc290419Sopenharmony_ci FindClose(hFind); 458cc290419Sopenharmony_ci#else 459cc290419Sopenharmony_ci DIR* dir = opendir(GetLogDirName().c_str()); 460cc290419Sopenharmony_ci if (dir == nullptr) { 461cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "open log dir failed"); 462cc290419Sopenharmony_ci return files; 463cc290419Sopenharmony_ci } 464cc290419Sopenharmony_ci 465cc290419Sopenharmony_ci struct dirent* entry; 466cc290419Sopenharmony_ci while ((entry = readdir(dir)) != nullptr) { 467cc290419Sopenharmony_ci string fileName = entry->d_name; 468cc290419Sopenharmony_ci if (strncmp(fileName.c_str(), LOG_FILE_NAME_PREFIX.c_str(), LOG_FILE_NAME_PREFIX.size()) == 0) { 469cc290419Sopenharmony_ci files.push_back(fileName); 470cc290419Sopenharmony_ci } 471cc290419Sopenharmony_ci } 472cc290419Sopenharmony_ci closedir(dir); 473cc290419Sopenharmony_ci#endif 474cc290419Sopenharmony_ci return files; 475cc290419Sopenharmony_ci } 476cc290419Sopenharmony_ci 477cc290419Sopenharmony_ci inline string GetLogDirName() 478cc290419Sopenharmony_ci { 479cc290419Sopenharmony_ci return GetTmpDir() + LOG_DIR_NAME + GetPathSep(); 480cc290419Sopenharmony_ci } 481cc290419Sopenharmony_ci 482cc290419Sopenharmony_ci string GetLogNameWithTime() 483cc290419Sopenharmony_ci { 484cc290419Sopenharmony_ci string timeStr; 485cc290419Sopenharmony_ci GetTimeString(timeStr); 486cc290419Sopenharmony_ci // example: hdc-20230228-123456789.log 487cc290419Sopenharmony_ci return LOG_FILE_NAME_PREFIX + timeStr + LOG_FILE_SUFFIX; 488cc290419Sopenharmony_ci } 489cc290419Sopenharmony_ci 490cc290419Sopenharmony_ci void RemoveOlderLogFiles() 491cc290419Sopenharmony_ci { 492cc290419Sopenharmony_ci vector<string> files = GetDirFileName(); 493cc290419Sopenharmony_ci uint16_t logLimitSize = GetLogLimitByEnv(); 494cc290419Sopenharmony_ci if (files.size() <= logLimitSize) { 495cc290419Sopenharmony_ci return; 496cc290419Sopenharmony_ci } 497cc290419Sopenharmony_ci // Sort file names by time, with newer ones coming first 498cc290419Sopenharmony_ci sort(files.begin(), files.end(), CompareLogFileName); 499cc290419Sopenharmony_ci uint32_t deleteCount = GetLogOverCount(files, MAX_LOG_DIR_SIZE); 500cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "log file count: %u, logLimit: %u", files.size(), logLimitSize); 501cc290419Sopenharmony_ci if (deleteCount == 0 || files.size() < deleteCount) { 502cc290419Sopenharmony_ci return; 503cc290419Sopenharmony_ci } 504cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "will delete log file, count: %u", deleteCount); 505cc290419Sopenharmony_ci uint32_t count = 0; 506cc290419Sopenharmony_ci uint32_t beginCount = files.size() - deleteCount; 507cc290419Sopenharmony_ci for (auto name : files) { 508cc290419Sopenharmony_ci count++; 509cc290419Sopenharmony_ci if (count < beginCount) { 510cc290419Sopenharmony_ci continue; 511cc290419Sopenharmony_ci } 512cc290419Sopenharmony_ci string deleteFile = GetLogDirName() + name; 513cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "delete: %s", deleteFile.c_str()); 514cc290419Sopenharmony_ci unlink(deleteFile.c_str()); 515cc290419Sopenharmony_ci } 516cc290419Sopenharmony_ci } 517cc290419Sopenharmony_ci 518cc290419Sopenharmony_ci void LogToFile(const char *str) 519cc290419Sopenharmony_ci { 520cc290419Sopenharmony_ci string path = GetLogDirName() + LOG_FILE_NAME; 521cc290419Sopenharmony_ci RollLogFile(path.c_str()); 522cc290419Sopenharmony_ci LogToPath(path.c_str(), str); 523cc290419Sopenharmony_ci } 524cc290419Sopenharmony_ci 525cc290419Sopenharmony_ci void LogToCache(const char *str) 526cc290419Sopenharmony_ci { 527cc290419Sopenharmony_ci string path = GetLogDirName() + LOG_CACHE_NAME; 528cc290419Sopenharmony_ci LogToPath(path.c_str(), str); 529cc290419Sopenharmony_ci } 530cc290419Sopenharmony_ci 531cc290419Sopenharmony_ci void RollLogFile(const char *path) 532cc290419Sopenharmony_ci { 533cc290419Sopenharmony_ci // Here cannot use WRITE_LOG, because WRITE_LOG will call RollLogFile again. 534cc290419Sopenharmony_ci int value = -1; 535cc290419Sopenharmony_ci uv_fs_t fs; 536cc290419Sopenharmony_ci value = uv_fs_stat(nullptr, &fs, path, nullptr); 537cc290419Sopenharmony_ci if (value != 0) { 538cc290419Sopenharmony_ci constexpr int bufSize = 1024; 539cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 540cc290419Sopenharmony_ci uv_strerror_r(value, buf, bufSize); 541cc290419Sopenharmony_ci PrintMessage("RollLogFile error log file %s not exist %s", path, buf); 542cc290419Sopenharmony_ci return; 543cc290419Sopenharmony_ci } 544cc290419Sopenharmony_ci uint64_t size = fs.statbuf.st_size; 545cc290419Sopenharmony_ci if (size < MAX_LOG_FILE_SIZE) { 546cc290419Sopenharmony_ci return; 547cc290419Sopenharmony_ci } 548cc290419Sopenharmony_ci string last = GetLogDirName() + GetLogNameWithTime(); 549cc290419Sopenharmony_ci value = uv_fs_rename(nullptr, &fs, path, last.c_str(), nullptr); 550cc290419Sopenharmony_ci PrintMessage("rename %s to %s", path, last.c_str()); 551cc290419Sopenharmony_ci if (value != 0) { 552cc290419Sopenharmony_ci constexpr int bufSize = 1024; 553cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 554cc290419Sopenharmony_ci uv_strerror_r(value, buf, bufSize); 555cc290419Sopenharmony_ci uv_fs_req_cleanup(&fs); 556cc290419Sopenharmony_ci PrintMessage("RollLogFile error rename %s to %s %s", path, last.c_str(), buf); 557cc290419Sopenharmony_ci return; 558cc290419Sopenharmony_ci } 559cc290419Sopenharmony_ci uv_fs_req_cleanup(&fs); 560cc290419Sopenharmony_ci // creat thread 561cc290419Sopenharmony_ci std::thread compressDirThread(CompressLogFiles); 562cc290419Sopenharmony_ci compressDirThread.detach(); 563cc290419Sopenharmony_ci RemoveOlderLogFiles(); 564cc290419Sopenharmony_ci } 565cc290419Sopenharmony_ci 566cc290419Sopenharmony_ci void ChmodLogFile() 567cc290419Sopenharmony_ci { 568cc290419Sopenharmony_ci string path = GetLogDirName() + LOG_FILE_NAME; 569cc290419Sopenharmony_ci uv_fs_t req = {}; 570cc290419Sopenharmony_ci int rc = uv_fs_chmod(nullptr, &req, path.c_str(), 0664, nullptr); 571cc290419Sopenharmony_ci if (rc < 0) { 572cc290419Sopenharmony_ci char buffer[BUF_SIZE_DEFAULT] = { 0 }; 573cc290419Sopenharmony_ci uv_strerror_r(rc, buffer, BUF_SIZE_DEFAULT); 574cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "uv_fs_chmod %s failed %s", path.c_str(), buffer); 575cc290419Sopenharmony_ci } 576cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 577cc290419Sopenharmony_ci } 578cc290419Sopenharmony_ci#endif 579cc290419Sopenharmony_ci 580cc290419Sopenharmony_civoid PrintLogEx(const char *functionName, int line, uint8_t logLevel, const char *msg, ...) 581cc290419Sopenharmony_ci { 582cc290419Sopenharmony_ci if (logLevel > g_logLevel) { 583cc290419Sopenharmony_ci return; 584cc290419Sopenharmony_ci } 585cc290419Sopenharmony_ci 586cc290419Sopenharmony_ci char buf[BUF_SIZE_DEFAULT4] = { 0 }; // only 4k to avoid stack overflow in 32bit or L0 587cc290419Sopenharmony_ci va_list vaArgs; 588cc290419Sopenharmony_ci va_start(vaArgs, msg); 589cc290419Sopenharmony_ci const int retSize = vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, msg, vaArgs); 590cc290419Sopenharmony_ci va_end(vaArgs); 591cc290419Sopenharmony_ci if (retSize < 0) { 592cc290419Sopenharmony_ci return; 593cc290419Sopenharmony_ci } 594cc290419Sopenharmony_ci 595cc290419Sopenharmony_ci#ifdef HDC_HILOG 596cc290419Sopenharmony_ci string tmpPath = functionName; 597cc290419Sopenharmony_ci string filePath = GetFileNameAny(tmpPath); 598cc290419Sopenharmony_ci switch (static_cast<int>(logLevel)) { 599cc290419Sopenharmony_ci case static_cast<int>(LOG_DEBUG): 600cc290419Sopenharmony_ci // Info level log can be printed default in hilog, debug can't 601cc290419Sopenharmony_ci HDC_LOG_INFO("[%{public}s:%{public}d] %{public}s", 602cc290419Sopenharmony_ci filePath.c_str(), line, buf); 603cc290419Sopenharmony_ci break; 604cc290419Sopenharmony_ci case static_cast<int>(LOG_INFO): 605cc290419Sopenharmony_ci HDC_LOG_INFO("[%{public}s:%{public}d] %{public}s", 606cc290419Sopenharmony_ci filePath.c_str(), line, buf); 607cc290419Sopenharmony_ci break; 608cc290419Sopenharmony_ci case static_cast<int>(LOG_WARN): 609cc290419Sopenharmony_ci HDC_LOG_WARN("[%{public}s:%{public}d] %{public}s", 610cc290419Sopenharmony_ci filePath.c_str(), line, buf); 611cc290419Sopenharmony_ci break; 612cc290419Sopenharmony_ci case static_cast<int>(LOG_FATAL): 613cc290419Sopenharmony_ci HDC_LOG_FATAL("[%{public}s:%{public}d] %{public}s", 614cc290419Sopenharmony_ci filePath.c_str(), line, buf); 615cc290419Sopenharmony_ci break; 616cc290419Sopenharmony_ci default: 617cc290419Sopenharmony_ci break; 618cc290419Sopenharmony_ci } 619cc290419Sopenharmony_ci#else 620cc290419Sopenharmony_ci string logLevelString; 621cc290419Sopenharmony_ci string threadIdString; 622cc290419Sopenharmony_ci string sep = "\n"; 623cc290419Sopenharmony_ci string timeString; 624cc290419Sopenharmony_ci if (string(buf).back() == '\n') { 625cc290419Sopenharmony_ci sep = "\r\n"; 626cc290419Sopenharmony_ci } 627cc290419Sopenharmony_ci string debugInfo = functionName; 628cc290419Sopenharmony_ci GetLogDebugFunctionName(debugInfo, line, threadIdString); 629cc290419Sopenharmony_ci GetLogLevelAndTime(logLevel, logLevelString, timeString); 630cc290419Sopenharmony_ci string logBuf = StringFormat("[%s][%s]%s%s %s%s", logLevelString.c_str(), timeString.c_str(), 631cc290419Sopenharmony_ci threadIdString.c_str(), debugInfo.c_str(), buf, sep.c_str()); 632cc290419Sopenharmony_ci 633cc290419Sopenharmony_ci printf("%s", logBuf.c_str()); 634cc290419Sopenharmony_ci fflush(stdout); 635cc290419Sopenharmony_ci 636cc290419Sopenharmony_ci if (!g_logCache) { 637cc290419Sopenharmony_ci LogToFile(logBuf.c_str()); 638cc290419Sopenharmony_ci } else { 639cc290419Sopenharmony_ci LogToCache(logBuf.c_str()); 640cc290419Sopenharmony_ci } 641cc290419Sopenharmony_ci#endif 642cc290419Sopenharmony_ci return; 643cc290419Sopenharmony_ci } 644cc290419Sopenharmony_ci#else // else ENABLE_DEBUGLOG.If disabled, the entire output code will be optimized by the compiler 645cc290419Sopenharmony_ci void PrintLogEx(const char *functionName, int line, uint8_t logLevel, char *msg, ...) 646cc290419Sopenharmony_ci { 647cc290419Sopenharmony_ci } 648cc290419Sopenharmony_ci#endif // ENABLE_DEBUGLOG 649cc290419Sopenharmony_ci 650cc290419Sopenharmony_ci void PrintMessage(const char *fmt, ...) 651cc290419Sopenharmony_ci { 652cc290419Sopenharmony_ci va_list ap; 653cc290419Sopenharmony_ci va_start(ap, fmt); 654cc290419Sopenharmony_ci if (vfprintf(stdout, fmt, ap) > 0) { 655cc290419Sopenharmony_ci fprintf(stdout, "\n"); 656cc290419Sopenharmony_ci } 657cc290419Sopenharmony_ci va_end(ap); 658cc290419Sopenharmony_ci } 659cc290419Sopenharmony_ci 660cc290419Sopenharmony_ci // if can linkwith -lstdc++fs, use std::filesystem::path(path).filename(); 661cc290419Sopenharmony_ci string GetFileNameAny(string &path) 662cc290419Sopenharmony_ci { 663cc290419Sopenharmony_ci string tmpString = path; 664cc290419Sopenharmony_ci size_t tmpNum = tmpString.rfind('/'); 665cc290419Sopenharmony_ci if (tmpNum == std::string::npos) { 666cc290419Sopenharmony_ci tmpNum = tmpString.rfind('\\'); 667cc290419Sopenharmony_ci if (tmpNum == std::string::npos) { 668cc290419Sopenharmony_ci return tmpString; 669cc290419Sopenharmony_ci } 670cc290419Sopenharmony_ci } 671cc290419Sopenharmony_ci tmpString = tmpString.substr(tmpNum + 1, tmpString.size() - tmpNum); 672cc290419Sopenharmony_ci return tmpString; 673cc290419Sopenharmony_ci } 674cc290419Sopenharmony_ci 675cc290419Sopenharmony_ci void SetTcpOptions(uv_tcp_t *tcpHandle, int bufMaxSize) 676cc290419Sopenharmony_ci { 677cc290419Sopenharmony_ci if (!tcpHandle) { 678cc290419Sopenharmony_ci return; 679cc290419Sopenharmony_ci } 680cc290419Sopenharmony_ci uv_tcp_keepalive(tcpHandle, 1, GLOBAL_TIMEOUT); 681cc290419Sopenharmony_ci // if MAX_SIZE_IOBUF==5k,bufMaxSize at least 40k. It must be set to io 8 times is more appropriate, 682cc290419Sopenharmony_ci // otherwise asynchronous IO is too fast, a lot of IO is wasted on IOloop, transmission speed will decrease 683cc290419Sopenharmony_ci 684cc290419Sopenharmony_ci uv_recv_buffer_size((uv_handle_t *)tcpHandle, &bufMaxSize); 685cc290419Sopenharmony_ci uv_send_buffer_size((uv_handle_t *)tcpHandle, &bufMaxSize); 686cc290419Sopenharmony_ci } 687cc290419Sopenharmony_ci 688cc290419Sopenharmony_ci void ReallocBuf(uint8_t **origBuf, int *nOrigSize, size_t sizeWanted) 689cc290419Sopenharmony_ci { 690cc290419Sopenharmony_ci if (*nOrigSize > 0) { 691cc290419Sopenharmony_ci return; 692cc290419Sopenharmony_ci } 693cc290419Sopenharmony_ci if (sizeWanted <= 0 || sizeWanted >= HDC_BUF_MAX_BYTES) { 694cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "ReallocBuf failed, sizeWanted:%d", sizeWanted); 695cc290419Sopenharmony_ci return; 696cc290419Sopenharmony_ci } 697cc290419Sopenharmony_ci *origBuf = new uint8_t[sizeWanted]; 698cc290419Sopenharmony_ci if (!*origBuf) { 699cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "ReallocBuf failed, origBuf is null. sizeWanted:%d", sizeWanted); 700cc290419Sopenharmony_ci return; 701cc290419Sopenharmony_ci } 702cc290419Sopenharmony_ci *nOrigSize = sizeWanted; 703cc290419Sopenharmony_ci } 704cc290419Sopenharmony_ci 705cc290419Sopenharmony_ci // As an uv_alloc_cb it must keep the same as prototype 706cc290419Sopenharmony_ci void AllocBufferCallback(uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf) 707cc290419Sopenharmony_ci { 708cc290419Sopenharmony_ci const int size = GetMaxBufSizeStable(); 709cc290419Sopenharmony_ci buf->base = (char *)new uint8_t[size](); 710cc290419Sopenharmony_ci if (buf->base) { 711cc290419Sopenharmony_ci buf->len = size - 1; 712cc290419Sopenharmony_ci } 713cc290419Sopenharmony_ci } 714cc290419Sopenharmony_ci 715cc290419Sopenharmony_ci // As an uv_write_cb it must keep the same as prototype 716cc290419Sopenharmony_ci void SendCallback(uv_write_t *req, int status) 717cc290419Sopenharmony_ci { 718cc290419Sopenharmony_ci StartTraceScope("Base::SendCallback"); 719cc290419Sopenharmony_ci if (status < 0) { 720cc290419Sopenharmony_ci constexpr int bufSize = 1024; 721cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 722cc290419Sopenharmony_ci uv_strerror_r(status, buf, bufSize); 723cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "SendCallback failed,status:%d %s", status, buf); 724cc290419Sopenharmony_ci } 725cc290419Sopenharmony_ci delete[]((uint8_t *)req->data); 726cc290419Sopenharmony_ci delete req; 727cc290419Sopenharmony_ci } 728cc290419Sopenharmony_ci 729cc290419Sopenharmony_ci // xxx must keep sync with uv_loop_close/uv_walk etc. 730cc290419Sopenharmony_ci bool TryCloseLoop(uv_loop_t *ptrLoop, const char *callerName) 731cc290419Sopenharmony_ci { 732cc290419Sopenharmony_ci // UV_RUN_DEFAULT: Runs the event loop until the reference count drops to zero. Always returns zero. 733cc290419Sopenharmony_ci // UV_RUN_ONCE: Poll for new events once. Note that this function blocks if there are no pending events. 734cc290419Sopenharmony_ci // Returns zero when done (no active handles or requests left), or non-zero if more events are 735cc290419Sopenharmony_ci // expected meaning you should run the event loop again sometime in the future). 736cc290419Sopenharmony_ci // UV_RUN_NOWAIT: Poll for new events once but don't block if there are no pending events. 737cc290419Sopenharmony_ci uint8_t closeRetry = 0; 738cc290419Sopenharmony_ci bool ret = false; 739cc290419Sopenharmony_ci constexpr int maxRetry = 3; 740cc290419Sopenharmony_ci for (closeRetry = 0; closeRetry < maxRetry; ++closeRetry) { 741cc290419Sopenharmony_ci if (uv_loop_close(ptrLoop) == UV_EBUSY) { 742cc290419Sopenharmony_ci if (closeRetry > 2) { // 2:try 2 times close,the 3rd try shows uv loop cannot close. 743cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s close busy,try:%d", callerName, closeRetry); 744cc290419Sopenharmony_ci } 745cc290419Sopenharmony_ci 746cc290419Sopenharmony_ci if (ptrLoop->active_handles >= 2) { // 2:at least 2 handles for read & write. 747cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "TryCloseLoop issue"); 748cc290419Sopenharmony_ci } 749cc290419Sopenharmony_ci auto clearLoopTask = [](uv_handle_t *handle, void *arg) -> void { TryCloseHandle(handle); }; 750cc290419Sopenharmony_ci uv_walk(ptrLoop, clearLoopTask, nullptr); 751cc290419Sopenharmony_ci // If all processing ends, Then return0,this call will block 752cc290419Sopenharmony_ci if (!ptrLoop->active_handles) { 753cc290419Sopenharmony_ci ret = true; 754cc290419Sopenharmony_ci break; 755cc290419Sopenharmony_ci } 756cc290419Sopenharmony_ci if (!uv_run(ptrLoop, UV_RUN_ONCE)) { 757cc290419Sopenharmony_ci ret = true; 758cc290419Sopenharmony_ci break; 759cc290419Sopenharmony_ci } 760cc290419Sopenharmony_ci usleep(10000); // 10000:sleep for 10s 761cc290419Sopenharmony_ci } else { 762cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Try close loop success"); 763cc290419Sopenharmony_ci ret = true; 764cc290419Sopenharmony_ci break; 765cc290419Sopenharmony_ci } 766cc290419Sopenharmony_ci } 767cc290419Sopenharmony_ci return ret; 768cc290419Sopenharmony_ci } 769cc290419Sopenharmony_ci 770cc290419Sopenharmony_ci // xxx must keep sync with uv_loop_close/uv_walk etc. 771cc290419Sopenharmony_ci bool TryCloseChildLoop(uv_loop_t *ptrLoop, const char *callerName) 772cc290419Sopenharmony_ci { 773cc290419Sopenharmony_ci // UV_RUN_DEFAULT: Runs the event loop until the reference count drops to zero. Always returns zero. 774cc290419Sopenharmony_ci // UV_RUN_ONCE: Poll for new events once. Note that this function blocks if there are no pending events. 775cc290419Sopenharmony_ci // Returns zero when done (no active handles or requests left), or non-zero if more events are 776cc290419Sopenharmony_ci // expected meaning you should run the event loop again sometime in the future). 777cc290419Sopenharmony_ci // UV_RUN_NOWAIT: Poll for new events once but don't block if there are no pending events. 778cc290419Sopenharmony_ci uint8_t closeRetry = 0; 779cc290419Sopenharmony_ci bool ret = false; 780cc290419Sopenharmony_ci constexpr int maxRetry = 3; 781cc290419Sopenharmony_ci for (closeRetry = 0; closeRetry < maxRetry; ++closeRetry) { 782cc290419Sopenharmony_ci if (uv_loop_close(ptrLoop) == UV_EBUSY) { 783cc290419Sopenharmony_ci if (closeRetry > 2) { // 2:try 2 times close,the 3rd try shows uv loop cannot close. 784cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s close busy,try:%d", callerName, closeRetry); 785cc290419Sopenharmony_ci } 786cc290419Sopenharmony_ci 787cc290419Sopenharmony_ci if (ptrLoop->active_handles >= 2) { // 2:at least 2 handles for read & write. 788cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "TryCloseLoop issue"); 789cc290419Sopenharmony_ci } 790cc290419Sopenharmony_ci auto clearLoopTask = [](uv_handle_t *handle, void *arg) -> void { TryCloseHandle(handle); }; 791cc290419Sopenharmony_ci uv_walk(ptrLoop, clearLoopTask, nullptr); 792cc290419Sopenharmony_ci#ifdef _WIN32 793cc290419Sopenharmony_ci // If all processing ends, Then return0,this call will block 794cc290419Sopenharmony_ci if (!ptrLoop->active_handles) { 795cc290419Sopenharmony_ci ret = true; 796cc290419Sopenharmony_ci break; 797cc290419Sopenharmony_ci } 798cc290419Sopenharmony_ci if (!uv_run(ptrLoop, UV_RUN_ONCE)) { 799cc290419Sopenharmony_ci ret = true; 800cc290419Sopenharmony_ci break; 801cc290419Sopenharmony_ci } 802cc290419Sopenharmony_ci usleep(10000); // 10000:sleep for 10s 803cc290419Sopenharmony_ci#else 804cc290419Sopenharmony_ci int r = 0; 805cc290419Sopenharmony_ci int count = 0; 806cc290419Sopenharmony_ci do { 807cc290419Sopenharmony_ci count++; 808cc290419Sopenharmony_ci r = uv_run(ptrLoop, UV_RUN_NOWAIT); 809cc290419Sopenharmony_ci uv_sleep(MILL_SECONDS); //10 millseconds 810cc290419Sopenharmony_ci } while (r != 0 && count <= COUNT); 811cc290419Sopenharmony_ci#endif 812cc290419Sopenharmony_ci } else { 813cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Try close loop success"); 814cc290419Sopenharmony_ci ret = true; 815cc290419Sopenharmony_ci break; 816cc290419Sopenharmony_ci } 817cc290419Sopenharmony_ci } 818cc290419Sopenharmony_ci return ret; 819cc290419Sopenharmony_ci } 820cc290419Sopenharmony_ci 821cc290419Sopenharmony_ci // Some handles may not be initialized or activated yet or have been closed, skip the closing process 822cc290419Sopenharmony_ci void TryCloseHandle(const uv_handle_t *handle) 823cc290419Sopenharmony_ci { 824cc290419Sopenharmony_ci TryCloseHandle(handle, nullptr); 825cc290419Sopenharmony_ci } 826cc290419Sopenharmony_ci 827cc290419Sopenharmony_ci void TryCloseHandle(const uv_handle_t *handle, uv_close_cb closeCallBack) 828cc290419Sopenharmony_ci { 829cc290419Sopenharmony_ci TryCloseHandle(handle, false, closeCallBack); 830cc290419Sopenharmony_ci } 831cc290419Sopenharmony_ci 832cc290419Sopenharmony_ci void TryCloseHandle(const uv_handle_t *handle, bool alwaysCallback, uv_close_cb closeCallBack) 833cc290419Sopenharmony_ci { 834cc290419Sopenharmony_ci bool hasCallClose = false; 835cc290419Sopenharmony_ci if (handle->loop && !uv_is_closing(handle)) { 836cc290419Sopenharmony_ci DispUvStreamInfo((const uv_stream_t *)handle, "before uv handle close"); 837cc290419Sopenharmony_ci uv_close((uv_handle_t *)handle, closeCallBack); 838cc290419Sopenharmony_ci hasCallClose = true; 839cc290419Sopenharmony_ci } 840cc290419Sopenharmony_ci if (!hasCallClose && alwaysCallback) { 841cc290419Sopenharmony_ci closeCallBack((uv_handle_t *)handle); 842cc290419Sopenharmony_ci } 843cc290419Sopenharmony_ci } 844cc290419Sopenharmony_ci 845cc290419Sopenharmony_ci void DispUvStreamInfo(const uv_stream_t *handle, const char *prefix) 846cc290419Sopenharmony_ci { 847cc290419Sopenharmony_ci uv_handle_type type = handle->type; 848cc290419Sopenharmony_ci string name = "unknown"; 849cc290419Sopenharmony_ci if (type == UV_TCP) { 850cc290419Sopenharmony_ci name = "tcp"; 851cc290419Sopenharmony_ci } else if (type == UV_NAMED_PIPE) { 852cc290419Sopenharmony_ci name = "named_pipe"; 853cc290419Sopenharmony_ci } else { 854cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s, the uv handle type is %d", prefix, type); 855cc290419Sopenharmony_ci return; 856cc290419Sopenharmony_ci } 857cc290419Sopenharmony_ci 858cc290419Sopenharmony_ci size_t bufNotSended = uv_stream_get_write_queue_size(handle); 859cc290419Sopenharmony_ci if (bufNotSended != 0) { 860cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s, the uv handle type is %s, has %u bytes data", prefix, name.c_str(), bufNotSended); 861cc290419Sopenharmony_ci } 862cc290419Sopenharmony_ci } 863cc290419Sopenharmony_ci int SendToStream(uv_stream_t *handleStream, const uint8_t *buf, const int bufLen) 864cc290419Sopenharmony_ci { 865cc290419Sopenharmony_ci StartTraceScope("Base::SendToStream"); 866cc290419Sopenharmony_ci if (bufLen > static_cast<int>(HDC_BUF_MAX_BYTES)) { 867cc290419Sopenharmony_ci return ERR_BUF_ALLOC; 868cc290419Sopenharmony_ci } 869cc290419Sopenharmony_ci uint8_t *pDynBuf = new uint8_t[bufLen]; 870cc290419Sopenharmony_ci if (!pDynBuf) { 871cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "SendToStream, alloc failed, size:%d", bufLen); 872cc290419Sopenharmony_ci return ERR_BUF_ALLOC; 873cc290419Sopenharmony_ci } 874cc290419Sopenharmony_ci if (memcpy_s(pDynBuf, bufLen, buf, bufLen)) { 875cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "SendToStream, memory copy failed, size:%d", bufLen); 876cc290419Sopenharmony_ci delete[] pDynBuf; 877cc290419Sopenharmony_ci return ERR_BUF_COPY; 878cc290419Sopenharmony_ci } 879cc290419Sopenharmony_ci return SendToStreamEx(handleStream, pDynBuf, bufLen, nullptr, 880cc290419Sopenharmony_ci reinterpret_cast<void *>(SendCallback), reinterpret_cast<void *>(pDynBuf)); 881cc290419Sopenharmony_ci } 882cc290419Sopenharmony_ci 883cc290419Sopenharmony_ci // handleSend is used for pipe thread sending, set nullptr for tcp, and dynamically allocated by malloc when buf 884cc290419Sopenharmony_ci // is required 885cc290419Sopenharmony_ci int SendToStreamEx(uv_stream_t *handleStream, const uint8_t *buf, const int bufLen, uv_stream_t *handleSend, 886cc290419Sopenharmony_ci const void *finishCallback, const void *pWriteReqData) 887cc290419Sopenharmony_ci { 888cc290419Sopenharmony_ci StartTraceScope("Base::SendToStreamEx"); 889cc290419Sopenharmony_ci int ret = ERR_GENERIC; 890cc290419Sopenharmony_ci uv_write_t *reqWrite = new uv_write_t(); 891cc290419Sopenharmony_ci if (!reqWrite) { 892cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "SendToStreamEx, new write_t failed, size:%d", bufLen); 893cc290419Sopenharmony_ci return ERR_BUF_ALLOC; 894cc290419Sopenharmony_ci } 895cc290419Sopenharmony_ci uv_buf_t bfr; 896cc290419Sopenharmony_ci while (true) { 897cc290419Sopenharmony_ci reqWrite->data = (void *)pWriteReqData; 898cc290419Sopenharmony_ci bfr.base = (char *)buf; 899cc290419Sopenharmony_ci bfr.len = bufLen; 900cc290419Sopenharmony_ci if (!uv_is_writable(handleStream)) { 901cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "SendToStreamEx, uv_is_writable false, size:%d", bufLen); 902cc290419Sopenharmony_ci delete reqWrite; 903cc290419Sopenharmony_ci break; 904cc290419Sopenharmony_ci } 905cc290419Sopenharmony_ci // handleSend must be a TCP socket or pipe, which is a server or a connection (listening or 906cc290419Sopenharmony_ci // connected state). Bound sockets or pipes will be assumed to be servers. 907cc290419Sopenharmony_ci if (handleSend) { 908cc290419Sopenharmony_ci ret = uv_write2(reqWrite, handleStream, &bfr, 1, handleSend, (uv_write_cb)finishCallback); 909cc290419Sopenharmony_ci } else { 910cc290419Sopenharmony_ci ret = uv_write(reqWrite, handleStream, &bfr, 1, (uv_write_cb)finishCallback); 911cc290419Sopenharmony_ci } 912cc290419Sopenharmony_ci if (ret < 0) { 913cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "SendToStreamEx, uv_write false, size:%d", bufLen); 914cc290419Sopenharmony_ci delete reqWrite; 915cc290419Sopenharmony_ci ret = ERR_IO_FAIL; 916cc290419Sopenharmony_ci break; 917cc290419Sopenharmony_ci } 918cc290419Sopenharmony_ci ret = bufLen; 919cc290419Sopenharmony_ci break; 920cc290419Sopenharmony_ci } 921cc290419Sopenharmony_ci return ret; 922cc290419Sopenharmony_ci } 923cc290419Sopenharmony_ci 924cc290419Sopenharmony_ci int SendToPollFd(int fd, const uint8_t *buf, const int bufLen) 925cc290419Sopenharmony_ci { 926cc290419Sopenharmony_ci if (bufLen > static_cast<int>(HDC_BUF_MAX_BYTES)) { 927cc290419Sopenharmony_ci return ERR_BUF_ALLOC; 928cc290419Sopenharmony_ci } 929cc290419Sopenharmony_ci uint8_t *pDynBuf = new uint8_t[bufLen]; 930cc290419Sopenharmony_ci if (!pDynBuf) { 931cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "SendToPollFd, alloc failed, size:%d", bufLen); 932cc290419Sopenharmony_ci return ERR_BUF_ALLOC; 933cc290419Sopenharmony_ci } 934cc290419Sopenharmony_ci if (memcpy_s(pDynBuf, bufLen, buf, bufLen)) { 935cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "SendToPollFd, memory copy failed, size:%d", bufLen); 936cc290419Sopenharmony_ci delete[] pDynBuf; 937cc290419Sopenharmony_ci return ERR_BUF_COPY; 938cc290419Sopenharmony_ci } 939cc290419Sopenharmony_ci int ret = Base::WriteToFd(fd, pDynBuf, bufLen); 940cc290419Sopenharmony_ci delete[] pDynBuf; 941cc290419Sopenharmony_ci if (ret <= 0) { 942cc290419Sopenharmony_ci hdc_strerrno(buf); 943cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "SendToPollFd, send %d bytes to fd %d failed [%d][%s]", bufLen, fd, ret, buf); 944cc290419Sopenharmony_ci } 945cc290419Sopenharmony_ci return ret; 946cc290419Sopenharmony_ci } 947cc290419Sopenharmony_ci 948cc290419Sopenharmony_ci uint64_t GetRuntimeMSec() 949cc290419Sopenharmony_ci { 950cc290419Sopenharmony_ci struct timespec times = { 0, 0 }; 951cc290419Sopenharmony_ci long time; 952cc290419Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, ×); 953cc290419Sopenharmony_ci time = times.tv_sec * TIME_BASE + times.tv_nsec / (TIME_BASE * TIME_BASE); 954cc290419Sopenharmony_ci return time; 955cc290419Sopenharmony_ci } 956cc290419Sopenharmony_ci 957cc290419Sopenharmony_ci uint32_t GetRandomU32() 958cc290419Sopenharmony_ci { 959cc290419Sopenharmony_ci uint32_t ret; 960cc290419Sopenharmony_ci std::random_device rd; 961cc290419Sopenharmony_ci std::mt19937 gen(rd()); 962cc290419Sopenharmony_ci std::uniform_int_distribution<uint32_t> dis(0, UINT32_MAX); 963cc290419Sopenharmony_ci ret = dis(gen); 964cc290419Sopenharmony_ci return ret; 965cc290419Sopenharmony_ci } 966cc290419Sopenharmony_ci 967cc290419Sopenharmony_ci uint64_t GetRandom(const uint64_t min, const uint64_t max) 968cc290419Sopenharmony_ci { 969cc290419Sopenharmony_ci#ifdef HARMONY_PROJECT 970cc290419Sopenharmony_ci uint64_t ret; 971cc290419Sopenharmony_ci uv_random(nullptr, nullptr, &ret, sizeof(ret), 0, nullptr); 972cc290419Sopenharmony_ci#else 973cc290419Sopenharmony_ci uint64_t ret; 974cc290419Sopenharmony_ci std::random_device rd; 975cc290419Sopenharmony_ci std::mt19937 gen(rd()); 976cc290419Sopenharmony_ci std::uniform_int_distribution<uint64_t> dis(min, max); 977cc290419Sopenharmony_ci ret = dis(gen); 978cc290419Sopenharmony_ci#endif 979cc290419Sopenharmony_ci return ret; 980cc290419Sopenharmony_ci } 981cc290419Sopenharmony_ci 982cc290419Sopenharmony_ci uint32_t GetSecureRandom(void) 983cc290419Sopenharmony_ci { 984cc290419Sopenharmony_ci uint32_t result = static_cast<uint32_t>(GetRandom()); 985cc290419Sopenharmony_ci#ifdef _WIN32 986cc290419Sopenharmony_ci const int randomByteCount = 4; 987cc290419Sopenharmony_ci HCRYPTPROV hCryptProv; 988cc290419Sopenharmony_ci BYTE pbData[randomByteCount]; 989cc290419Sopenharmony_ci do { 990cc290419Sopenharmony_ci if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) { 991cc290419Sopenharmony_ci if (GetLastError() != NTE_BAD_KEYSET) { 992cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "CryptAcquireContext first failed %x", GetLastError()); 993cc290419Sopenharmony_ci break; 994cc290419Sopenharmony_ci } 995cc290419Sopenharmony_ci if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { 996cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "CryptAcquireContext second failed %x", GetLastError()); 997cc290419Sopenharmony_ci break; 998cc290419Sopenharmony_ci } 999cc290419Sopenharmony_ci } 1000cc290419Sopenharmony_ci if (!CryptGenRandom(hCryptProv, randomByteCount, pbData)) { 1001cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "CryptGenRandom failed %x", GetLastError()); 1002cc290419Sopenharmony_ci } 1003cc290419Sopenharmony_ci if (hCryptProv) { 1004cc290419Sopenharmony_ci CryptReleaseContext(hCryptProv, 0); 1005cc290419Sopenharmony_ci } 1006cc290419Sopenharmony_ci result = *(reinterpret_cast<uint32_t*>(pbData)); 1007cc290419Sopenharmony_ci } while (0); 1008cc290419Sopenharmony_ci#else 1009cc290419Sopenharmony_ci std::ifstream randomFile("/dev/random", std::ios::binary); 1010cc290419Sopenharmony_ci do { 1011cc290419Sopenharmony_ci if (!randomFile.is_open()) { 1012cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "open /dev/random failed"); 1013cc290419Sopenharmony_ci break; 1014cc290419Sopenharmony_ci } 1015cc290419Sopenharmony_ci randomFile.read(reinterpret_cast<char*>(&result), sizeof(result)); 1016cc290419Sopenharmony_ci } while (0); 1017cc290419Sopenharmony_ci randomFile.close(); 1018cc290419Sopenharmony_ci#endif 1019cc290419Sopenharmony_ci return result; 1020cc290419Sopenharmony_ci } 1021cc290419Sopenharmony_ci 1022cc290419Sopenharmony_ci string GetRandomString(const uint16_t expectedLen) 1023cc290419Sopenharmony_ci { 1024cc290419Sopenharmony_ci srand(static_cast<unsigned int>(GetRandom())); 1025cc290419Sopenharmony_ci string ret = string(expectedLen, '0'); 1026cc290419Sopenharmony_ci std::stringstream val; 1027cc290419Sopenharmony_ci for (auto i = 0; i < expectedLen; ++i) { 1028cc290419Sopenharmony_ci val << std::hex << (rand() % BUF_SIZE_MICRO); 1029cc290419Sopenharmony_ci } 1030cc290419Sopenharmony_ci ret = val.str(); 1031cc290419Sopenharmony_ci return ret; 1032cc290419Sopenharmony_ci } 1033cc290419Sopenharmony_ci 1034cc290419Sopenharmony_ci#ifndef HDC_HOST 1035cc290419Sopenharmony_ci string GetSecureRandomString(const uint16_t expectedLen) 1036cc290419Sopenharmony_ci { 1037cc290419Sopenharmony_ci string ret = string(expectedLen, '0'); 1038cc290419Sopenharmony_ci std::ifstream randomFile("/dev/random", std::ios::binary); 1039cc290419Sopenharmony_ci do { 1040cc290419Sopenharmony_ci if (!randomFile.is_open()) { 1041cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "open /dev/random failed"); 1042cc290419Sopenharmony_ci break; 1043cc290419Sopenharmony_ci } 1044cc290419Sopenharmony_ci std::stringstream val; 1045cc290419Sopenharmony_ci unsigned char tmpByte; 1046cc290419Sopenharmony_ci for (auto i = 0; i < expectedLen; ++i) { 1047cc290419Sopenharmony_ci randomFile.read(reinterpret_cast<char*>(&tmpByte), 1); 1048cc290419Sopenharmony_ci val << std::hex << (tmpByte % BUF_SIZE_MICRO); 1049cc290419Sopenharmony_ci } 1050cc290419Sopenharmony_ci ret = val.str(); 1051cc290419Sopenharmony_ci } while (0); 1052cc290419Sopenharmony_ci randomFile.close(); 1053cc290419Sopenharmony_ci 1054cc290419Sopenharmony_ci return ret; 1055cc290419Sopenharmony_ci } 1056cc290419Sopenharmony_ci#endif 1057cc290419Sopenharmony_ci 1058cc290419Sopenharmony_ci int GetRandomNum(const int min, const int max) 1059cc290419Sopenharmony_ci { 1060cc290419Sopenharmony_ci return static_cast<int>(GetRandom(min, max)); 1061cc290419Sopenharmony_ci } 1062cc290419Sopenharmony_ci 1063cc290419Sopenharmony_ci int ConnectKey2IPPort(const char *connectKey, char *outIP, uint16_t *outPort, size_t outSize) 1064cc290419Sopenharmony_ci { 1065cc290419Sopenharmony_ci char bufString[BUF_SIZE_TINY] = ""; 1066cc290419Sopenharmony_ci if (strncpy_s(bufString, sizeof(bufString), connectKey, strlen(connectKey))) { 1067cc290419Sopenharmony_ci return ERR_BUF_COPY; 1068cc290419Sopenharmony_ci } 1069cc290419Sopenharmony_ci char *p = strrchr(bufString, ':'); 1070cc290419Sopenharmony_ci if (!p) { 1071cc290419Sopenharmony_ci return ERR_PARM_FORMAT; 1072cc290419Sopenharmony_ci } 1073cc290419Sopenharmony_ci *p = '\0'; 1074cc290419Sopenharmony_ci if (!strlen(bufString) || strlen(bufString) > 40) { // 40 : bigger than length of ipv6 1075cc290419Sopenharmony_ci return ERR_PARM_SIZE; 1076cc290419Sopenharmony_ci } 1077cc290419Sopenharmony_ci uint16_t wPort = static_cast<uint16_t>(atoi(p + 1)); 1078cc290419Sopenharmony_ci if (EOK != strcpy_s(outIP, outSize, bufString)) { 1079cc290419Sopenharmony_ci return ERR_BUF_COPY; 1080cc290419Sopenharmony_ci } 1081cc290419Sopenharmony_ci *outPort = wPort; 1082cc290419Sopenharmony_ci return RET_SUCCESS; 1083cc290419Sopenharmony_ci } 1084cc290419Sopenharmony_ci 1085cc290419Sopenharmony_ci // After creating the session worker thread, execute it on the main thread 1086cc290419Sopenharmony_ci void FinishWorkThread(uv_work_t *req, int status) 1087cc290419Sopenharmony_ci { 1088cc290419Sopenharmony_ci // This is operated in the main thread 1089cc290419Sopenharmony_ci delete req; 1090cc290419Sopenharmony_ci } 1091cc290419Sopenharmony_ci 1092cc290419Sopenharmony_ci // at the finish of pFuncAfterThread must free uv_work_t* 1093cc290419Sopenharmony_ci // clang-format off 1094cc290419Sopenharmony_ci int StartWorkThread(uv_loop_t *loop, uv_work_cb pFuncWorkThread, 1095cc290419Sopenharmony_ci uv_after_work_cb pFuncAfterThread, void *pThreadData) 1096cc290419Sopenharmony_ci { 1097cc290419Sopenharmony_ci uv_work_t *workThread = new uv_work_t(); 1098cc290419Sopenharmony_ci if (!workThread) { 1099cc290419Sopenharmony_ci return -1; 1100cc290419Sopenharmony_ci } 1101cc290419Sopenharmony_ci workThread->data = pThreadData; 1102cc290419Sopenharmony_ci uv_queue_work(loop, workThread, pFuncWorkThread, pFuncAfterThread); 1103cc290419Sopenharmony_ci return 0; 1104cc290419Sopenharmony_ci } 1105cc290419Sopenharmony_ci // clang-format on 1106cc290419Sopenharmony_ci 1107cc290419Sopenharmony_ci char **SplitCommandToArgs(const char *cmdStringLine, int *slotIndex) 1108cc290419Sopenharmony_ci { 1109cc290419Sopenharmony_ci constexpr int extraBufSize = 2; 1110cc290419Sopenharmony_ci char **argv; 1111cc290419Sopenharmony_ci char *temp = nullptr; 1112cc290419Sopenharmony_ci int argc = 0; 1113cc290419Sopenharmony_ci char a = 0; 1114cc290419Sopenharmony_ci size_t i = 0; 1115cc290419Sopenharmony_ci size_t j = 0; 1116cc290419Sopenharmony_ci size_t len = 0; 1117cc290419Sopenharmony_ci bool isQuoted = false; 1118cc290419Sopenharmony_ci bool isText = false; 1119cc290419Sopenharmony_ci bool isSpace = false; 1120cc290419Sopenharmony_ci 1121cc290419Sopenharmony_ci len = strlen(cmdStringLine); 1122cc290419Sopenharmony_ci if (len < 1) { 1123cc290419Sopenharmony_ci return nullptr; 1124cc290419Sopenharmony_ci } 1125cc290419Sopenharmony_ci i = ((len + extraBufSize) / extraBufSize) * sizeof(void *) + sizeof(void *); 1126cc290419Sopenharmony_ci argv = reinterpret_cast<char **>(new(std::nothrow) char[i + (len + extraBufSize) * sizeof(char)]); 1127cc290419Sopenharmony_ci if (argv == nullptr) { 1128cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "SplitCommandToArgs new argv failed"); 1129cc290419Sopenharmony_ci return nullptr; 1130cc290419Sopenharmony_ci } 1131cc290419Sopenharmony_ci temp = reinterpret_cast<char *>((reinterpret_cast<uint8_t *>(argv)) + i); 1132cc290419Sopenharmony_ci argc = 0; 1133cc290419Sopenharmony_ci argv[argc] = temp; 1134cc290419Sopenharmony_ci isQuoted = false; 1135cc290419Sopenharmony_ci isText = false; 1136cc290419Sopenharmony_ci isSpace = true; 1137cc290419Sopenharmony_ci i = 0; 1138cc290419Sopenharmony_ci j = 0; 1139cc290419Sopenharmony_ci 1140cc290419Sopenharmony_ci while ((a = cmdStringLine[i]) != 0) { 1141cc290419Sopenharmony_ci if (isQuoted) { 1142cc290419Sopenharmony_ci if (a == '\"') { 1143cc290419Sopenharmony_ci isQuoted = false; 1144cc290419Sopenharmony_ci } else { 1145cc290419Sopenharmony_ci temp[j] = a; 1146cc290419Sopenharmony_ci ++j; 1147cc290419Sopenharmony_ci } 1148cc290419Sopenharmony_ci } else { 1149cc290419Sopenharmony_ci switch (a) { 1150cc290419Sopenharmony_ci case '\"': 1151cc290419Sopenharmony_ci isQuoted = true; 1152cc290419Sopenharmony_ci isText = true; 1153cc290419Sopenharmony_ci if (isSpace) { 1154cc290419Sopenharmony_ci argv[argc] = temp + j; 1155cc290419Sopenharmony_ci ++argc; 1156cc290419Sopenharmony_ci } 1157cc290419Sopenharmony_ci isSpace = false; 1158cc290419Sopenharmony_ci break; 1159cc290419Sopenharmony_ci case ' ': 1160cc290419Sopenharmony_ci case '\t': 1161cc290419Sopenharmony_ci case '\n': 1162cc290419Sopenharmony_ci case '\r': 1163cc290419Sopenharmony_ci if (isText) { 1164cc290419Sopenharmony_ci temp[j] = '\0'; 1165cc290419Sopenharmony_ci ++j; 1166cc290419Sopenharmony_ci } 1167cc290419Sopenharmony_ci isText = false; 1168cc290419Sopenharmony_ci isSpace = true; 1169cc290419Sopenharmony_ci break; 1170cc290419Sopenharmony_ci default: 1171cc290419Sopenharmony_ci isText = true; 1172cc290419Sopenharmony_ci if (isSpace) { 1173cc290419Sopenharmony_ci argv[argc] = temp + j; 1174cc290419Sopenharmony_ci ++argc; 1175cc290419Sopenharmony_ci } 1176cc290419Sopenharmony_ci temp[j] = a; 1177cc290419Sopenharmony_ci ++j; 1178cc290419Sopenharmony_ci isSpace = false; 1179cc290419Sopenharmony_ci break; 1180cc290419Sopenharmony_ci } 1181cc290419Sopenharmony_ci } 1182cc290419Sopenharmony_ci ++i; 1183cc290419Sopenharmony_ci } 1184cc290419Sopenharmony_ci temp[j] = '\0'; 1185cc290419Sopenharmony_ci argv[argc] = nullptr; 1186cc290419Sopenharmony_ci 1187cc290419Sopenharmony_ci (*slotIndex) = argc; 1188cc290419Sopenharmony_ci return argv; 1189cc290419Sopenharmony_ci } 1190cc290419Sopenharmony_ci 1191cc290419Sopenharmony_ci bool RunPipeComand(const char *cmdString, char *outBuf, uint16_t sizeOutBuf, bool ignoreTailLf) 1192cc290419Sopenharmony_ci { 1193cc290419Sopenharmony_ci FILE *pipeHandle = popen(cmdString, "r"); 1194cc290419Sopenharmony_ci if (pipeHandle == nullptr) { 1195cc290419Sopenharmony_ci return false; 1196cc290419Sopenharmony_ci } 1197cc290419Sopenharmony_ci int bytesRead = 0; 1198cc290419Sopenharmony_ci int bytesOnce = 0; 1199cc290419Sopenharmony_ci while (!feof(pipeHandle)) { 1200cc290419Sopenharmony_ci bytesOnce = fread(outBuf, 1, sizeOutBuf - bytesRead, pipeHandle); 1201cc290419Sopenharmony_ci if (bytesOnce <= 0) { 1202cc290419Sopenharmony_ci break; 1203cc290419Sopenharmony_ci } 1204cc290419Sopenharmony_ci bytesRead += bytesOnce; 1205cc290419Sopenharmony_ci } 1206cc290419Sopenharmony_ci if (bytesRead && ignoreTailLf) { 1207cc290419Sopenharmony_ci if (outBuf[bytesRead - 1] == '\n') { 1208cc290419Sopenharmony_ci outBuf[bytesRead - 1] = '\0'; 1209cc290419Sopenharmony_ci } 1210cc290419Sopenharmony_ci } 1211cc290419Sopenharmony_ci pclose(pipeHandle); 1212cc290419Sopenharmony_ci return bytesRead; 1213cc290419Sopenharmony_ci } 1214cc290419Sopenharmony_ci 1215cc290419Sopenharmony_ci // bufLen == 0: alloc buffer in heap, need free it later 1216cc290419Sopenharmony_ci // >0: read max nBuffLen bytes to *buff 1217cc290419Sopenharmony_ci // ret value: <0 or bytes read 1218cc290419Sopenharmony_ci int ReadBinFile(const char *pathName, void **buf, const size_t bufLen) 1219cc290419Sopenharmony_ci { 1220cc290419Sopenharmony_ci uint8_t *pDst = nullptr; 1221cc290419Sopenharmony_ci size_t byteIO = 0; 1222cc290419Sopenharmony_ci uv_fs_t req; 1223cc290419Sopenharmony_ci int ret = uv_fs_stat(nullptr, &req, pathName, nullptr); 1224cc290419Sopenharmony_ci if (ret < 0) { 1225cc290419Sopenharmony_ci char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1226cc290419Sopenharmony_ci uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1227cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 1228cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ReadBinFile uv_fs_stat %s error %s", pathName, buffer); 1229cc290419Sopenharmony_ci return -1; 1230cc290419Sopenharmony_ci } 1231cc290419Sopenharmony_ci size_t nFileSize = req.statbuf.st_size; 1232cc290419Sopenharmony_ci size_t readMax = 0; 1233cc290419Sopenharmony_ci uint8_t dynamicBuf = 0; 1234cc290419Sopenharmony_ci ret = -3; // -3:error for ReadBinFile 1235cc290419Sopenharmony_ci if (bufLen == 0) { 1236cc290419Sopenharmony_ci dynamicBuf = 1; 1237cc290419Sopenharmony_ci pDst = new uint8_t[nFileSize + 1](); // tail \0 1238cc290419Sopenharmony_ci if (!pDst) { 1239cc290419Sopenharmony_ci return -1; 1240cc290419Sopenharmony_ci } 1241cc290419Sopenharmony_ci readMax = nFileSize; 1242cc290419Sopenharmony_ci } else { 1243cc290419Sopenharmony_ci if (nFileSize > bufLen) { 1244cc290419Sopenharmony_ci return -2; // -2:error for bufLen 1245cc290419Sopenharmony_ci } 1246cc290419Sopenharmony_ci readMax = nFileSize; 1247cc290419Sopenharmony_ci pDst = reinterpret_cast<uint8_t *>(buf); // The first address of the static array is the array address 1248cc290419Sopenharmony_ci } 1249cc290419Sopenharmony_ci 1250cc290419Sopenharmony_ci string srcPath(pathName); 1251cc290419Sopenharmony_ci string resolvedPath = CanonicalizeSpecPath(srcPath); 1252cc290419Sopenharmony_ci uv_buf_t rbf = uv_buf_init((char *)pDst, readMax); 1253cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 1254cc290419Sopenharmony_ci int fd = uv_fs_open(nullptr, &req, resolvedPath.c_str(), O_RDONLY, 0, nullptr); 1255cc290419Sopenharmony_ci if (fd < 0) { 1256cc290419Sopenharmony_ci char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1257cc290419Sopenharmony_ci uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1258cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ReadBinFile uv_fs_open %s error %s", resolvedPath.c_str(), buffer); 1259cc290419Sopenharmony_ci goto ReadFileFromPath_Finish; 1260cc290419Sopenharmony_ci } 1261cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 1262cc290419Sopenharmony_ci byteIO = uv_fs_read(nullptr, &req, fd, &rbf, 1, 0, nullptr); 1263cc290419Sopenharmony_ci uv_fs_close(nullptr, nullptr, fd, nullptr); 1264cc290419Sopenharmony_ci if (byteIO != readMax) { 1265cc290419Sopenharmony_ci char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1266cc290419Sopenharmony_ci uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1267cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ReadBinFile uv_fs_read %s error %s byteIO:%llu readMax:%llu", 1268cc290419Sopenharmony_ci resolvedPath.c_str(), buffer, byteIO, readMax); 1269cc290419Sopenharmony_ci goto ReadFileFromPath_Finish; 1270cc290419Sopenharmony_ci } 1271cc290419Sopenharmony_ci ret = 0; 1272cc290419Sopenharmony_ci ReadFileFromPath_Finish: 1273cc290419Sopenharmony_ci if (ret) { 1274cc290419Sopenharmony_ci if (dynamicBuf) { 1275cc290419Sopenharmony_ci delete[] pDst; 1276cc290419Sopenharmony_ci } 1277cc290419Sopenharmony_ci } else { 1278cc290419Sopenharmony_ci if (dynamicBuf) { 1279cc290419Sopenharmony_ci *buf = pDst; 1280cc290419Sopenharmony_ci } 1281cc290419Sopenharmony_ci ret = byteIO; 1282cc290419Sopenharmony_ci } 1283cc290419Sopenharmony_ci return ret; 1284cc290419Sopenharmony_ci } 1285cc290419Sopenharmony_ci 1286cc290419Sopenharmony_ci int WriteBinFile(const char *pathName, const uint8_t *buf, const size_t bufLen, bool newFile) 1287cc290419Sopenharmony_ci { 1288cc290419Sopenharmony_ci string resolvedPath; 1289cc290419Sopenharmony_ci string srcPath(pathName); 1290cc290419Sopenharmony_ci int flags = 0; 1291cc290419Sopenharmony_ci if (newFile) { 1292cc290419Sopenharmony_ci flags = UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_TRUNC; 1293cc290419Sopenharmony_ci // no std::fs supoort, else std::filesystem::canonical,-lstdc++fs 1294cc290419Sopenharmony_ci if (srcPath.find("..") != string::npos) { 1295cc290419Sopenharmony_ci return ERR_FILE_PATH_CHECK; 1296cc290419Sopenharmony_ci } 1297cc290419Sopenharmony_ci resolvedPath = srcPath.c_str(); 1298cc290419Sopenharmony_ci } else { 1299cc290419Sopenharmony_ci flags = UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_APPEND; 1300cc290419Sopenharmony_ci resolvedPath = CanonicalizeSpecPath(srcPath); 1301cc290419Sopenharmony_ci } 1302cc290419Sopenharmony_ci uv_fs_t req; 1303cc290419Sopenharmony_ci int fd = uv_fs_open(nullptr, &req, resolvedPath.c_str(), flags, S_IWUSR | S_IRUSR, nullptr); 1304cc290419Sopenharmony_ci if (fd < 0) { 1305cc290419Sopenharmony_ci char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1306cc290419Sopenharmony_ci uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1307cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 1308cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "WriteBinFile uv_fs_open %s error %s", resolvedPath.c_str(), buffer); 1309cc290419Sopenharmony_ci return ERR_FILE_OPEN; 1310cc290419Sopenharmony_ci } 1311cc290419Sopenharmony_ci uv_buf_t wbf = uv_buf_init((char *)buf, bufLen); 1312cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 1313cc290419Sopenharmony_ci size_t bytesDone = uv_fs_write(nullptr, &req, fd, &wbf, 1, 0, nullptr); 1314cc290419Sopenharmony_ci uv_fs_close(nullptr, &req, fd, nullptr); 1315cc290419Sopenharmony_ci if (bytesDone != bufLen) { 1316cc290419Sopenharmony_ci char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1317cc290419Sopenharmony_ci uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1318cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 1319cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "WriteBinFile uv_fs_write %s error %s bytesDone:%llu bufLen:%llu", 1320cc290419Sopenharmony_ci resolvedPath.c_str(), buffer, bytesDone, bufLen); 1321cc290419Sopenharmony_ci return ERR_BUF_SIZE; 1322cc290419Sopenharmony_ci } 1323cc290419Sopenharmony_ci return RET_SUCCESS; 1324cc290419Sopenharmony_ci } 1325cc290419Sopenharmony_ci 1326cc290419Sopenharmony_ci void CloseIdleCallback(uv_handle_t *handle) 1327cc290419Sopenharmony_ci { 1328cc290419Sopenharmony_ci delete (uv_idle_t *)handle; 1329cc290419Sopenharmony_ci }; 1330cc290419Sopenharmony_ci 1331cc290419Sopenharmony_ci void CloseTimerCallback(uv_handle_t *handle) 1332cc290419Sopenharmony_ci { 1333cc290419Sopenharmony_ci delete (uv_timer_t *)handle; 1334cc290419Sopenharmony_ci }; 1335cc290419Sopenharmony_ci 1336cc290419Sopenharmony_ci // return value: <0 error; 0 can start new server instance; >0 server already exists 1337cc290419Sopenharmony_ci int ProgramMutex(const char *procname, bool checkOrNew) 1338cc290419Sopenharmony_ci { 1339cc290419Sopenharmony_ci char bufPath[BUF_SIZE_DEFAULT] = ""; 1340cc290419Sopenharmony_ci char buf[BUF_SIZE_DEFAULT] = ""; 1341cc290419Sopenharmony_ci char pidBuf[BUF_SIZE_TINY] = ""; 1342cc290419Sopenharmony_ci size_t size = sizeof(buf); 1343cc290419Sopenharmony_ci if (uv_os_tmpdir(buf, &size) < 0) { 1344cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Tmppath failed"); 1345cc290419Sopenharmony_ci return ERR_API_FAIL; 1346cc290419Sopenharmony_ci } 1347cc290419Sopenharmony_ci if (snprintf_s(bufPath, sizeof(bufPath), sizeof(bufPath) - 1, "%s%c.%s.pid", buf, Base::GetPathSep(), procname) 1348cc290419Sopenharmony_ci < 0) { 1349cc290419Sopenharmony_ci return ERR_BUF_OVERFLOW; 1350cc290419Sopenharmony_ci } 1351cc290419Sopenharmony_ci int pid = static_cast<int>(getpid()); 1352cc290419Sopenharmony_ci if (snprintf_s(pidBuf, sizeof(pidBuf), sizeof(pidBuf) - 1, "%d", pid) < 0) { 1353cc290419Sopenharmony_ci return ERR_BUF_OVERFLOW; 1354cc290419Sopenharmony_ci } 1355cc290419Sopenharmony_ci // no need to CanonicalizeSpecPath, else not work 1356cc290419Sopenharmony_ci umask(0); 1357cc290419Sopenharmony_ci uv_fs_t req; 1358cc290419Sopenharmony_ci int fd = uv_fs_open(nullptr, &req, bufPath, O_RDWR | O_CREAT, 0666, nullptr); // 0666:permission 1359cc290419Sopenharmony_ci if (fd < 0) { 1360cc290419Sopenharmony_ci char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1361cc290419Sopenharmony_ci uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1362cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 1363cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Open mutex file %s failed!!! %s", bufPath, buffer); 1364cc290419Sopenharmony_ci return ERR_FILE_OPEN; 1365cc290419Sopenharmony_ci } 1366cc290419Sopenharmony_ci#ifdef _WIN32 1367cc290419Sopenharmony_ci if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "Global\\%s", procname) < 0) { 1368cc290419Sopenharmony_ci uv_fs_close(nullptr, &req, fd, nullptr); 1369cc290419Sopenharmony_ci return ERR_BUF_OVERFLOW; 1370cc290419Sopenharmony_ci } 1371cc290419Sopenharmony_ci if (checkOrNew) { 1372cc290419Sopenharmony_ci // CheckOrNew is true means to confirm whether the service is running 1373cc290419Sopenharmony_ci uv_fs_close(nullptr, &req, fd, nullptr); 1374cc290419Sopenharmony_ci HANDLE hMutex = OpenMutex(SYNCHRONIZE, FALSE, buf); 1375cc290419Sopenharmony_ci if (hMutex != nullptr) { 1376cc290419Sopenharmony_ci CloseHandle(hMutex); 1377cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Mutex \"%s\" locked. Server already exist.", procname); 1378cc290419Sopenharmony_ci return 1; 1379cc290419Sopenharmony_ci } else { 1380cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Server is not exist"); 1381cc290419Sopenharmony_ci return 0; 1382cc290419Sopenharmony_ci } 1383cc290419Sopenharmony_ci } else { 1384cc290419Sopenharmony_ci HANDLE hMutex = CreateMutex(nullptr, TRUE, buf); 1385cc290419Sopenharmony_ci DWORD dwError = GetLastError(); 1386cc290419Sopenharmony_ci if (ERROR_ALREADY_EXISTS == dwError || ERROR_ACCESS_DENIED == dwError) { 1387cc290419Sopenharmony_ci uv_fs_close(nullptr, &req, fd, nullptr); 1388cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Creat mutex, \"%s\" locked. proc already exit!!!\n", procname); 1389cc290419Sopenharmony_ci return 1; 1390cc290419Sopenharmony_ci } 1391cc290419Sopenharmony_ci } 1392cc290419Sopenharmony_ci#else 1393cc290419Sopenharmony_ci struct flock fl; 1394cc290419Sopenharmony_ci fl.l_type = F_WRLCK; 1395cc290419Sopenharmony_ci fl.l_start = 0; 1396cc290419Sopenharmony_ci fl.l_whence = SEEK_SET; 1397cc290419Sopenharmony_ci fl.l_len = 0; 1398cc290419Sopenharmony_ci int retChild = fcntl(fd, F_SETLK, &fl); 1399cc290419Sopenharmony_ci if (retChild == -1) { 1400cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "File \"%s\" locked. proc already exit!!!\n", bufPath); 1401cc290419Sopenharmony_ci uv_fs_close(nullptr, &req, fd, nullptr); 1402cc290419Sopenharmony_ci return 1; 1403cc290419Sopenharmony_ci } 1404cc290419Sopenharmony_ci#endif 1405cc290419Sopenharmony_ci int rc = 0; 1406cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 1407cc290419Sopenharmony_ci rc = uv_fs_ftruncate(nullptr, &req, fd, 0, nullptr); 1408cc290419Sopenharmony_ci if (rc == -1) { 1409cc290419Sopenharmony_ci char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1410cc290419Sopenharmony_ci uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1411cc290419Sopenharmony_ci uv_fs_close(nullptr, &req, fd, nullptr); 1412cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ftruncate file %s failed!!! %s", bufPath, buffer); 1413cc290419Sopenharmony_ci return ERR_FILE_STAT; 1414cc290419Sopenharmony_ci } 1415cc290419Sopenharmony_ci uv_buf_t wbf = uv_buf_init(pidBuf, strlen(pidBuf)); 1416cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 1417cc290419Sopenharmony_ci rc = uv_fs_write(nullptr, &req, fd, &wbf, 1, 0, nullptr); 1418cc290419Sopenharmony_ci if (rc == -1) { 1419cc290419Sopenharmony_ci char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1420cc290419Sopenharmony_ci uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1421cc290419Sopenharmony_ci uv_fs_close(nullptr, &req, fd, nullptr); 1422cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "write file %s failed!!! %s", bufPath, buffer); 1423cc290419Sopenharmony_ci return ERR_FILE_WRITE; 1424cc290419Sopenharmony_ci } 1425cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Write mutext to %s, pid:%s", bufPath, pidBuf); 1426cc290419Sopenharmony_ci if (checkOrNew) { 1427cc290419Sopenharmony_ci // close it for check only 1428cc290419Sopenharmony_ci uv_fs_close(nullptr, &req, fd, nullptr); 1429cc290419Sopenharmony_ci } 1430cc290419Sopenharmony_ci // Do not close the file descriptor, the process will be mutext effect under no-Win32 OS 1431cc290419Sopenharmony_ci return RET_SUCCESS; 1432cc290419Sopenharmony_ci } 1433cc290419Sopenharmony_ci 1434cc290419Sopenharmony_ci void SplitString(const string &origString, const string &seq, vector<string> &resultStrings) 1435cc290419Sopenharmony_ci { 1436cc290419Sopenharmony_ci string::size_type p1 = 0; 1437cc290419Sopenharmony_ci string::size_type p2 = origString.find(seq); 1438cc290419Sopenharmony_ci 1439cc290419Sopenharmony_ci while (p2 != string::npos) { 1440cc290419Sopenharmony_ci if (p2 == p1) { 1441cc290419Sopenharmony_ci ++p1; 1442cc290419Sopenharmony_ci p2 = origString.find(seq, p1); 1443cc290419Sopenharmony_ci continue; 1444cc290419Sopenharmony_ci } 1445cc290419Sopenharmony_ci resultStrings.push_back(origString.substr(p1, p2 - p1)); 1446cc290419Sopenharmony_ci p1 = p2 + seq.size(); 1447cc290419Sopenharmony_ci p2 = origString.find(seq, p1); 1448cc290419Sopenharmony_ci } 1449cc290419Sopenharmony_ci 1450cc290419Sopenharmony_ci if (p1 != origString.size()) { 1451cc290419Sopenharmony_ci resultStrings.push_back(origString.substr(p1)); 1452cc290419Sopenharmony_ci } 1453cc290419Sopenharmony_ci } 1454cc290419Sopenharmony_ci 1455cc290419Sopenharmony_ci string GetShellPath() 1456cc290419Sopenharmony_ci { 1457cc290419Sopenharmony_ci struct stat filecheck; 1458cc290419Sopenharmony_ci string shellPath = "/bin/sh"; 1459cc290419Sopenharmony_ci if (stat(shellPath.c_str(), &filecheck) < 0) { 1460cc290419Sopenharmony_ci shellPath = "/system/bin/sh"; 1461cc290419Sopenharmony_ci if (stat(shellPath.c_str(), &filecheck) < 0) { 1462cc290419Sopenharmony_ci shellPath = "sh"; 1463cc290419Sopenharmony_ci } 1464cc290419Sopenharmony_ci } 1465cc290419Sopenharmony_ci return shellPath; 1466cc290419Sopenharmony_ci } 1467cc290419Sopenharmony_ci 1468cc290419Sopenharmony_ci // Not supported on some platforms, Can only be achieved manually 1469cc290419Sopenharmony_ci uint64_t HostToNet(uint64_t val) 1470cc290419Sopenharmony_ci { 1471cc290419Sopenharmony_ci if (htonl(1) == 1) { 1472cc290419Sopenharmony_ci return val; 1473cc290419Sopenharmony_ci } 1474cc290419Sopenharmony_ci int offset = 32; 1475cc290419Sopenharmony_ci return ((static_cast<uint64_t>(htonl(val))) << offset) + htonl(val >> offset); 1476cc290419Sopenharmony_ci } 1477cc290419Sopenharmony_ci 1478cc290419Sopenharmony_ci uint64_t NetToHost(uint64_t val) 1479cc290419Sopenharmony_ci { 1480cc290419Sopenharmony_ci if (htonl(1) == 1) { 1481cc290419Sopenharmony_ci return val; 1482cc290419Sopenharmony_ci } 1483cc290419Sopenharmony_ci int offset = 32; 1484cc290419Sopenharmony_ci return ((static_cast<uint64_t>(ntohl(val))) << offset) + ntohl(val >> offset); 1485cc290419Sopenharmony_ci } 1486cc290419Sopenharmony_ci 1487cc290419Sopenharmony_ci char GetPathSep() 1488cc290419Sopenharmony_ci { 1489cc290419Sopenharmony_ci#ifdef _WIN32 1490cc290419Sopenharmony_ci const char sep = '\\'; 1491cc290419Sopenharmony_ci#else 1492cc290419Sopenharmony_ci const char sep = '/'; 1493cc290419Sopenharmony_ci#endif 1494cc290419Sopenharmony_ci return sep; 1495cc290419Sopenharmony_ci } 1496cc290419Sopenharmony_ci 1497cc290419Sopenharmony_ci string GetFullFilePath(string &s) 1498cc290419Sopenharmony_ci { // cannot use s.rfind(std::filesystem::path::preferred_separator 1499cc290419Sopenharmony_ci // remove last sep, and update input 1500cc290419Sopenharmony_ci while (s.back() == GetPathSep()) { 1501cc290419Sopenharmony_ci s.pop_back(); 1502cc290419Sopenharmony_ci } 1503cc290419Sopenharmony_ci 1504cc290419Sopenharmony_ci size_t i = s.rfind(GetPathSep(), s.length()); 1505cc290419Sopenharmony_ci if (i != string::npos) { 1506cc290419Sopenharmony_ci return (s.substr(i + 1, s.length() - i)); 1507cc290419Sopenharmony_ci } 1508cc290419Sopenharmony_ci return s; 1509cc290419Sopenharmony_ci } 1510cc290419Sopenharmony_ci 1511cc290419Sopenharmony_ci string GetPathWithoutFilename(const string &s) 1512cc290419Sopenharmony_ci { 1513cc290419Sopenharmony_ci size_t i = s.rfind(GetPathSep(), s.length()); 1514cc290419Sopenharmony_ci if (i != string::npos) { 1515cc290419Sopenharmony_ci return (s.substr(0, i + 1)); 1516cc290419Sopenharmony_ci } 1517cc290419Sopenharmony_ci return s; 1518cc290419Sopenharmony_ci } 1519cc290419Sopenharmony_ci 1520cc290419Sopenharmony_ci string GetHdcAbsolutePath() 1521cc290419Sopenharmony_ci { 1522cc290419Sopenharmony_ci char path[BUF_SIZE_DEFAULT4] = { 0 }; 1523cc290419Sopenharmony_ci size_t nPathSize = sizeof(path); 1524cc290419Sopenharmony_ci int ret = uv_exepath(path, &nPathSize); 1525cc290419Sopenharmony_ci if (ret < 0) { 1526cc290419Sopenharmony_ci char buf[BUF_SIZE_DEFAULT] = { 0 }; 1527cc290419Sopenharmony_ci uv_err_name_r(ret, buf, BUF_SIZE_DEFAULT); 1528cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "uvexepath ret:%d error:%s", ret, buf); 1529cc290419Sopenharmony_ci return ""; 1530cc290419Sopenharmony_ci } 1531cc290419Sopenharmony_ci 1532cc290419Sopenharmony_ci return string(path); 1533cc290419Sopenharmony_ci } 1534cc290419Sopenharmony_ci 1535cc290419Sopenharmony_ci int CreateSocketPair(int *fds) 1536cc290419Sopenharmony_ci { 1537cc290419Sopenharmony_ci#ifndef _WIN32 1538cc290419Sopenharmony_ci#ifdef HOST_MAC 1539cc290419Sopenharmony_ci int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); 1540cc290419Sopenharmony_ci if (ret == 0) { 1541cc290419Sopenharmony_ci for (auto i = 0; i < STREAM_SIZE; ++i) { 1542cc290419Sopenharmony_ci if (fcntl(fds[i], F_SETFD, FD_CLOEXEC) == -1) { 1543cc290419Sopenharmony_ci CloseFd(fds[0]); 1544cc290419Sopenharmony_ci CloseFd(fds[1]); 1545cc290419Sopenharmony_ci constexpr int bufSize = 1024; 1546cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 1547cc290419Sopenharmony_ci strerror_r(errno, buf, bufSize); 1548cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "fcntl failed to set FD_CLOEXEC: %s", buf); 1549cc290419Sopenharmony_ci return -1; 1550cc290419Sopenharmony_ci } 1551cc290419Sopenharmony_ci } 1552cc290419Sopenharmony_ci } 1553cc290419Sopenharmony_ci return ret; 1554cc290419Sopenharmony_ci#else 1555cc290419Sopenharmony_ci return socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds); 1556cc290419Sopenharmony_ci#endif 1557cc290419Sopenharmony_ci#else 1558cc290419Sopenharmony_ci struct sockaddr_in addr; 1559cc290419Sopenharmony_ci socklen_t addrlen = sizeof(addr); 1560cc290419Sopenharmony_ci int reuse = 1; 1561cc290419Sopenharmony_ci if (fds == 0) { 1562cc290419Sopenharmony_ci return -1; 1563cc290419Sopenharmony_ci } 1564cc290419Sopenharmony_ci int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 1565cc290419Sopenharmony_ci if (listener == -1) { 1566cc290419Sopenharmony_ci return -2; // -2:sockets error 1567cc290419Sopenharmony_ci } 1568cc290419Sopenharmony_ci Base::ZeroStruct(addr); 1569cc290419Sopenharmony_ci addr.sin_family = AF_INET; 1570cc290419Sopenharmony_ci addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1571cc290419Sopenharmony_ci addr.sin_port = 0; 1572cc290419Sopenharmony_ci fds[0] = fds[1] = (int)-1; 1573cc290419Sopenharmony_ci do { 1574cc290419Sopenharmony_ci if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, (socklen_t)sizeof(reuse))) { 1575cc290419Sopenharmony_ci break; 1576cc290419Sopenharmony_ci } 1577cc290419Sopenharmony_ci if (::bind(listener, (struct sockaddr *)&addr, sizeof(addr))) { 1578cc290419Sopenharmony_ci break; 1579cc290419Sopenharmony_ci } 1580cc290419Sopenharmony_ci if (getsockname(listener, (struct sockaddr *)&addr, &addrlen)) { 1581cc290419Sopenharmony_ci break; 1582cc290419Sopenharmony_ci } 1583cc290419Sopenharmony_ci if (listen(listener, 1)) { 1584cc290419Sopenharmony_ci break; 1585cc290419Sopenharmony_ci } 1586cc290419Sopenharmony_ci fds[0] = socket(AF_INET, SOCK_STREAM, 0); 1587cc290419Sopenharmony_ci if (fds[0] == -1) { 1588cc290419Sopenharmony_ci break; 1589cc290419Sopenharmony_ci } 1590cc290419Sopenharmony_ci if (connect(fds[0], (struct sockaddr *)&addr, sizeof(addr)) == -1) { 1591cc290419Sopenharmony_ci break; 1592cc290419Sopenharmony_ci } 1593cc290419Sopenharmony_ci fds[1] = accept(listener, nullptr, nullptr); 1594cc290419Sopenharmony_ci if (fds[1] == -1) { 1595cc290419Sopenharmony_ci break; 1596cc290419Sopenharmony_ci } 1597cc290419Sopenharmony_ci closesocket(listener); 1598cc290419Sopenharmony_ci return 0; 1599cc290419Sopenharmony_ci } while (0); 1600cc290419Sopenharmony_ci 1601cc290419Sopenharmony_ci closesocket(listener); 1602cc290419Sopenharmony_ci closesocket(fds[0]); 1603cc290419Sopenharmony_ci closesocket(fds[1]); 1604cc290419Sopenharmony_ci return -1; 1605cc290419Sopenharmony_ci#endif 1606cc290419Sopenharmony_ci } 1607cc290419Sopenharmony_ci 1608cc290419Sopenharmony_ci void CloseSocketPair(int *fds) 1609cc290419Sopenharmony_ci { 1610cc290419Sopenharmony_ci#ifndef _WIN32 1611cc290419Sopenharmony_ci CloseFd(fds[0]); 1612cc290419Sopenharmony_ci CloseFd(fds[1]); 1613cc290419Sopenharmony_ci#else 1614cc290419Sopenharmony_ci closesocket(fds[0]); 1615cc290419Sopenharmony_ci closesocket(fds[1]); 1616cc290419Sopenharmony_ci#endif 1617cc290419Sopenharmony_ci } 1618cc290419Sopenharmony_ci 1619cc290419Sopenharmony_ci int StringEndsWith(string s, string sub) 1620cc290419Sopenharmony_ci { 1621cc290419Sopenharmony_ci return s.rfind(sub) == (s.length() - sub.length()) ? 1 : 0; 1622cc290419Sopenharmony_ci } 1623cc290419Sopenharmony_ci 1624cc290419Sopenharmony_ci const char *GetFileType(mode_t mode) 1625cc290419Sopenharmony_ci { 1626cc290419Sopenharmony_ci switch (mode & S_IFMT) { 1627cc290419Sopenharmony_ci case S_IFDIR: 1628cc290419Sopenharmony_ci return "directory"; 1629cc290419Sopenharmony_ci case S_IFLNK: 1630cc290419Sopenharmony_ci return "symlink"; 1631cc290419Sopenharmony_ci case S_IFREG: 1632cc290419Sopenharmony_ci return "regular file"; 1633cc290419Sopenharmony_ci#ifndef _WIN32 1634cc290419Sopenharmony_ci case S_IFBLK: 1635cc290419Sopenharmony_ci return "block device"; 1636cc290419Sopenharmony_ci case S_IFCHR: 1637cc290419Sopenharmony_ci return "character device"; 1638cc290419Sopenharmony_ci case S_IFIFO: 1639cc290419Sopenharmony_ci return "FIFO/pipe"; 1640cc290419Sopenharmony_ci case S_IFSOCK: 1641cc290419Sopenharmony_ci return "socket"; 1642cc290419Sopenharmony_ci#endif 1643cc290419Sopenharmony_ci default: 1644cc290419Sopenharmony_ci return "Unknown"; 1645cc290419Sopenharmony_ci } 1646cc290419Sopenharmony_ci } 1647cc290419Sopenharmony_ci 1648cc290419Sopenharmony_ci void BuildErrorString(const char *localPath, const char *op, const char *err, string &str) 1649cc290419Sopenharmony_ci { 1650cc290419Sopenharmony_ci // avoid to use stringstream 1651cc290419Sopenharmony_ci str = op; 1652cc290419Sopenharmony_ci str += " "; 1653cc290419Sopenharmony_ci str += localPath; 1654cc290419Sopenharmony_ci str += " failed, "; 1655cc290419Sopenharmony_ci str += err; 1656cc290419Sopenharmony_ci } 1657cc290419Sopenharmony_ci 1658cc290419Sopenharmony_ci // Both absolute and relative paths support 1659cc290419Sopenharmony_ci bool CheckDirectoryOrPath(const char *localPath, bool pathOrDir, bool readWrite, string &errStr, mode_t &fm) 1660cc290419Sopenharmony_ci { 1661cc290419Sopenharmony_ci if (pathOrDir) { // filepath 1662cc290419Sopenharmony_ci uv_fs_t req; 1663cc290419Sopenharmony_ci mode_t mode; 1664cc290419Sopenharmony_ci fm = mode_t(~S_IFMT); 1665cc290419Sopenharmony_ci int r = uv_fs_lstat(nullptr, &req, localPath, nullptr); 1666cc290419Sopenharmony_ci if (r) { 1667cc290419Sopenharmony_ci constexpr int bufSize = 1024; 1668cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 1669cc290419Sopenharmony_ci uv_strerror_r((int)req.result, buf, bufSize); 1670cc290419Sopenharmony_ci BuildErrorString(localPath, "lstat", buf, errStr); 1671cc290419Sopenharmony_ci } 1672cc290419Sopenharmony_ci 1673cc290419Sopenharmony_ci mode = req.statbuf.st_mode; 1674cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 1675cc290419Sopenharmony_ci 1676cc290419Sopenharmony_ci if ((r == 0) && (mode & S_IFDIR)) { 1677cc290419Sopenharmony_ci fm = S_IFDIR; 1678cc290419Sopenharmony_ci } else if ((r == 0) && (mode & S_IFREG)) { // is file 1679cc290419Sopenharmony_ci uv_fs_access(nullptr, &req, localPath, readWrite ? R_OK : W_OK, nullptr); 1680cc290419Sopenharmony_ci if (req.result) { 1681cc290419Sopenharmony_ci const char *op = readWrite ? "access R_OK" : "access W_OK"; 1682cc290419Sopenharmony_ci constexpr int bufSize = 1024; 1683cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 1684cc290419Sopenharmony_ci uv_strerror_r((int)req.result, buf, bufSize); 1685cc290419Sopenharmony_ci BuildErrorString(localPath, op, buf, errStr); 1686cc290419Sopenharmony_ci } 1687cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 1688cc290419Sopenharmony_ci if (req.result == 0) { 1689cc290419Sopenharmony_ci return true; 1690cc290419Sopenharmony_ci } 1691cc290419Sopenharmony_ci } else if (r == 0) { 1692cc290419Sopenharmony_ci const char *type = GetFileType(mode); 1693cc290419Sopenharmony_ci errStr = "Not support "; 1694cc290419Sopenharmony_ci errStr += type; 1695cc290419Sopenharmony_ci errStr += ": "; 1696cc290419Sopenharmony_ci errStr += localPath; 1697cc290419Sopenharmony_ci } 1698cc290419Sopenharmony_ci } else { // dir 1699cc290419Sopenharmony_ci errStr = "Not support dir: "; 1700cc290419Sopenharmony_ci errStr += localPath; 1701cc290419Sopenharmony_ci } 1702cc290419Sopenharmony_ci return false; 1703cc290419Sopenharmony_ci } 1704cc290419Sopenharmony_ci 1705cc290419Sopenharmony_ci bool TryCreateDirectory(const string &path, string &err) 1706cc290419Sopenharmony_ci { 1707cc290419Sopenharmony_ci uv_fs_t req; 1708cc290419Sopenharmony_ci int r = uv_fs_lstat(nullptr, &req, path.c_str(), nullptr); 1709cc290419Sopenharmony_ci mode_t mode = req.statbuf.st_mode; 1710cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 1711cc290419Sopenharmony_ci if (r < 0) { 1712cc290419Sopenharmony_ci r = uv_fs_mkdir(nullptr, &req, path.c_str(), DEF_FILE_PERMISSION, nullptr); 1713cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "path not exist create dir = %s", path.c_str()); 1714cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 1715cc290419Sopenharmony_ci if (r < 0) { 1716cc290419Sopenharmony_ci constexpr int bufSize = 1024; 1717cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 1718cc290419Sopenharmony_ci uv_strerror_r((int)req.result, buf, bufSize); 1719cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "create dir %s failed %s", path.c_str(), buf); 1720cc290419Sopenharmony_ci err = "Error create directory, path:"; 1721cc290419Sopenharmony_ci err += path.c_str(); 1722cc290419Sopenharmony_ci return false; 1723cc290419Sopenharmony_ci } 1724cc290419Sopenharmony_ci } else { 1725cc290419Sopenharmony_ci if (!((mode & S_IFMT) == S_IFDIR)) { 1726cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s exist, not directory", path.c_str()); 1727cc290419Sopenharmony_ci err = "File exists, path:"; 1728cc290419Sopenharmony_ci err += path.c_str(); 1729cc290419Sopenharmony_ci return false; 1730cc290419Sopenharmony_ci } 1731cc290419Sopenharmony_ci } 1732cc290419Sopenharmony_ci return true; 1733cc290419Sopenharmony_ci } 1734cc290419Sopenharmony_ci 1735cc290419Sopenharmony_ci bool CheckDirectoryOrPath(const char *localPath, bool pathOrDir, bool readWrite) 1736cc290419Sopenharmony_ci { 1737cc290419Sopenharmony_ci string strUnused; 1738cc290419Sopenharmony_ci mode_t mode = mode_t(~S_IFMT); 1739cc290419Sopenharmony_ci return CheckDirectoryOrPath(localPath, pathOrDir, readWrite, strUnused, mode); 1740cc290419Sopenharmony_ci } 1741cc290419Sopenharmony_ci 1742cc290419Sopenharmony_ci // Using openssl encryption and decryption method, high efficiency; when encrypting more than 64 bytes, 1743cc290419Sopenharmony_ci // the carriage return will not be added, and the tail padding 00 is removed when decrypting 1744cc290419Sopenharmony_ci // The return value is the length of the string after Base64 1745cc290419Sopenharmony_ci int Base64EncodeBuf(const uint8_t *input, const int length, uint8_t *bufOut) 1746cc290419Sopenharmony_ci { 1747cc290419Sopenharmony_ci return EVP_EncodeBlock(bufOut, input, length); 1748cc290419Sopenharmony_ci } 1749cc290419Sopenharmony_ci 1750cc290419Sopenharmony_ci vector<uint8_t> Base64Encode(const uint8_t *input, const int length) 1751cc290419Sopenharmony_ci { 1752cc290419Sopenharmony_ci vector<uint8_t> retVec; 1753cc290419Sopenharmony_ci uint8_t *pBuf = nullptr; 1754cc290419Sopenharmony_ci while (true) { 1755cc290419Sopenharmony_ci if (static_cast<uint32_t>(length) > HDC_BUF_MAX_BYTES) { 1756cc290419Sopenharmony_ci break; 1757cc290419Sopenharmony_ci } 1758cc290419Sopenharmony_ci int base64Size = length * 1.4 + 256; 1759cc290419Sopenharmony_ci if (!(pBuf = new uint8_t[base64Size]())) { 1760cc290419Sopenharmony_ci break; 1761cc290419Sopenharmony_ci } 1762cc290419Sopenharmony_ci int childRet = Base64EncodeBuf(input, length, pBuf); 1763cc290419Sopenharmony_ci if (childRet <= 0) { 1764cc290419Sopenharmony_ci break; 1765cc290419Sopenharmony_ci } 1766cc290419Sopenharmony_ci retVec.insert(retVec.begin(), pBuf, pBuf + childRet); 1767cc290419Sopenharmony_ci break; 1768cc290419Sopenharmony_ci } 1769cc290419Sopenharmony_ci if (pBuf) { 1770cc290419Sopenharmony_ci delete[] pBuf; 1771cc290419Sopenharmony_ci } 1772cc290419Sopenharmony_ci 1773cc290419Sopenharmony_ci return retVec; 1774cc290419Sopenharmony_ci } 1775cc290419Sopenharmony_ci 1776cc290419Sopenharmony_ci inline int CalcDecodeLength(const uint8_t *b64input) 1777cc290419Sopenharmony_ci { 1778cc290419Sopenharmony_ci int len = strlen(reinterpret_cast<char *>(const_cast<uint8_t *>(b64input))); 1779cc290419Sopenharmony_ci if (!len) { 1780cc290419Sopenharmony_ci return 0; 1781cc290419Sopenharmony_ci } 1782cc290419Sopenharmony_ci int padding = 0; 1783cc290419Sopenharmony_ci if (b64input[len - 1] == '=' && b64input[len - LAST_EQUAL_NUM] == '=') { 1784cc290419Sopenharmony_ci // last two chars are = 1785cc290419Sopenharmony_ci padding = 2; // 2 : last two chars 1786cc290419Sopenharmony_ci } else if (b64input[len - 1] == '=') { 1787cc290419Sopenharmony_ci // last char is = 1788cc290419Sopenharmony_ci padding = 1; 1789cc290419Sopenharmony_ci } 1790cc290419Sopenharmony_ci return static_cast<int>(len * DECODE_SCALE - padding); 1791cc290419Sopenharmony_ci } 1792cc290419Sopenharmony_ci 1793cc290419Sopenharmony_ci // return -1 error; >0 decode size 1794cc290419Sopenharmony_ci int Base64DecodeBuf(const uint8_t *input, const int length, uint8_t *bufOut) 1795cc290419Sopenharmony_ci { 1796cc290419Sopenharmony_ci int nRetLen = CalcDecodeLength(input); 1797cc290419Sopenharmony_ci if (!nRetLen) { 1798cc290419Sopenharmony_ci return 0; 1799cc290419Sopenharmony_ci } 1800cc290419Sopenharmony_ci 1801cc290419Sopenharmony_ci if (EVP_DecodeBlock(bufOut, input, length) > 0) { 1802cc290419Sopenharmony_ci return nRetLen; 1803cc290419Sopenharmony_ci } 1804cc290419Sopenharmony_ci return 0; 1805cc290419Sopenharmony_ci } 1806cc290419Sopenharmony_ci 1807cc290419Sopenharmony_ci string Base64Decode(const uint8_t *input, const int length) 1808cc290419Sopenharmony_ci { 1809cc290419Sopenharmony_ci string retString; 1810cc290419Sopenharmony_ci uint8_t *pBuf = nullptr; 1811cc290419Sopenharmony_ci while (true) { 1812cc290419Sopenharmony_ci if (static_cast<uint32_t>(length) > HDC_BUF_MAX_BYTES) { 1813cc290419Sopenharmony_ci break; 1814cc290419Sopenharmony_ci } 1815cc290419Sopenharmony_ci // must less than length 1816cc290419Sopenharmony_ci if (!(pBuf = new uint8_t[length]())) { 1817cc290419Sopenharmony_ci break; 1818cc290419Sopenharmony_ci } 1819cc290419Sopenharmony_ci int childRet = Base64DecodeBuf(input, length, pBuf); 1820cc290419Sopenharmony_ci if (childRet <= 0) { 1821cc290419Sopenharmony_ci break; 1822cc290419Sopenharmony_ci } 1823cc290419Sopenharmony_ci retString = (reinterpret_cast<char *>(pBuf)); 1824cc290419Sopenharmony_ci break; 1825cc290419Sopenharmony_ci } 1826cc290419Sopenharmony_ci if (pBuf) { 1827cc290419Sopenharmony_ci delete[] pBuf; 1828cc290419Sopenharmony_ci } 1829cc290419Sopenharmony_ci return retString; 1830cc290419Sopenharmony_ci } 1831cc290419Sopenharmony_ci 1832cc290419Sopenharmony_ci void ReverseBytes(void *start, int size) 1833cc290419Sopenharmony_ci { 1834cc290419Sopenharmony_ci uint8_t *istart = (uint8_t *)start; 1835cc290419Sopenharmony_ci uint8_t *iend = istart + size; 1836cc290419Sopenharmony_ci std::reverse(istart, iend); 1837cc290419Sopenharmony_ci } 1838cc290419Sopenharmony_ci 1839cc290419Sopenharmony_ci string Convert2HexStr(uint8_t arr[], int length) 1840cc290419Sopenharmony_ci { 1841cc290419Sopenharmony_ci std::stringstream ss; 1842cc290419Sopenharmony_ci const int byteHexStrLen = 2; 1843cc290419Sopenharmony_ci for (int i = 0; i < length; i++) { 1844cc290419Sopenharmony_ci ss << std::hex << std::setw(byteHexStrLen) << std::setfill('0') 1845cc290419Sopenharmony_ci << static_cast<int>(arr[i]); 1846cc290419Sopenharmony_ci if (i < length - 1) { 1847cc290419Sopenharmony_ci ss << ":"; 1848cc290419Sopenharmony_ci } 1849cc290419Sopenharmony_ci } 1850cc290419Sopenharmony_ci string result = ss.str(); 1851cc290419Sopenharmony_ci transform(result.begin(), result.end(), result.begin(), ::toupper); 1852cc290419Sopenharmony_ci return result; 1853cc290419Sopenharmony_ci } 1854cc290419Sopenharmony_ci 1855cc290419Sopenharmony_ci // clang-format off 1856cc290419Sopenharmony_ci const string StringFormat(const char * const formater, ...) 1857cc290419Sopenharmony_ci { 1858cc290419Sopenharmony_ci va_list vaArgs; 1859cc290419Sopenharmony_ci va_start(vaArgs, formater); 1860cc290419Sopenharmony_ci string ret = StringFormat(formater, vaArgs); 1861cc290419Sopenharmony_ci va_end(vaArgs); 1862cc290419Sopenharmony_ci return ret; 1863cc290419Sopenharmony_ci } 1864cc290419Sopenharmony_ci 1865cc290419Sopenharmony_ci const string StringFormat(const char * const formater, va_list &vaArgs) 1866cc290419Sopenharmony_ci { 1867cc290419Sopenharmony_ci std::vector<char> args(GetMaxBufSizeStable()); 1868cc290419Sopenharmony_ci const int retSize = vsnprintf_s( 1869cc290419Sopenharmony_ci args.data(), GetMaxBufSizeStable(), (args.size() >= 1) ? (args.size() - 1) : 0, formater, vaArgs); 1870cc290419Sopenharmony_ci if (retSize < 0) { 1871cc290419Sopenharmony_ci return std::string(""); 1872cc290419Sopenharmony_ci } else { 1873cc290419Sopenharmony_ci return std::string(args.data(), retSize); 1874cc290419Sopenharmony_ci } 1875cc290419Sopenharmony_ci } 1876cc290419Sopenharmony_ci // clang-format on 1877cc290419Sopenharmony_ci 1878cc290419Sopenharmony_ci string GetVersion() 1879cc290419Sopenharmony_ci { 1880cc290419Sopenharmony_ci const uint8_t a = 'a'; 1881cc290419Sopenharmony_ci uint8_t major = (HDC_VERSION_NUMBER >> 28) & 0xff; 1882cc290419Sopenharmony_ci uint8_t minor = (HDC_VERSION_NUMBER << 4 >> 24) & 0xff; 1883cc290419Sopenharmony_ci uint8_t version = (HDC_VERSION_NUMBER << 12 >> 24) & 0xff; 1884cc290419Sopenharmony_ci uint8_t fix = (HDC_VERSION_NUMBER << 20 >> 28) & 0xff; // max 16, tail is p 1885cc290419Sopenharmony_ci string ver = StringFormat("%x.%x.%x%c", major, minor, version, a + fix); 1886cc290419Sopenharmony_ci return "Ver: " + ver; 1887cc290419Sopenharmony_ci } 1888cc290419Sopenharmony_ci 1889cc290419Sopenharmony_ci bool IdleUvTask(uv_loop_t *loop, void *data, uv_idle_cb cb) 1890cc290419Sopenharmony_ci { 1891cc290419Sopenharmony_ci uv_idle_t *idle = new(std::nothrow) uv_idle_t(); 1892cc290419Sopenharmony_ci if (idle == nullptr) { 1893cc290419Sopenharmony_ci return false; 1894cc290419Sopenharmony_ci } 1895cc290419Sopenharmony_ci idle->data = data; 1896cc290419Sopenharmony_ci uv_idle_init(loop, idle); 1897cc290419Sopenharmony_ci uv_idle_start(idle, cb); 1898cc290419Sopenharmony_ci // delete by callback 1899cc290419Sopenharmony_ci return true; 1900cc290419Sopenharmony_ci } 1901cc290419Sopenharmony_ci 1902cc290419Sopenharmony_ci bool TimerUvTask(uv_loop_t *loop, void *data, uv_timer_cb cb, int repeatTimeout) 1903cc290419Sopenharmony_ci { 1904cc290419Sopenharmony_ci uv_timer_t *timer = new(std::nothrow) uv_timer_t(); 1905cc290419Sopenharmony_ci if (timer == nullptr) { 1906cc290419Sopenharmony_ci return false; 1907cc290419Sopenharmony_ci } 1908cc290419Sopenharmony_ci timer->data = data; 1909cc290419Sopenharmony_ci uv_timer_init(loop, timer); 1910cc290419Sopenharmony_ci uv_timer_start(timer, cb, 0, repeatTimeout); 1911cc290419Sopenharmony_ci // delete by callback 1912cc290419Sopenharmony_ci return true; 1913cc290419Sopenharmony_ci } 1914cc290419Sopenharmony_ci 1915cc290419Sopenharmony_ci // callback, uint8_t flag, string msg, const void * data 1916cc290419Sopenharmony_ci bool DelayDo(uv_loop_t *loop, const int delayMs, const uint8_t flag, string msg, void *data, 1917cc290419Sopenharmony_ci std::function<void(const uint8_t, string &, const void *)> cb) 1918cc290419Sopenharmony_ci { 1919cc290419Sopenharmony_ci struct DelayDoParam { 1920cc290419Sopenharmony_ci uv_timer_t handle; 1921cc290419Sopenharmony_ci uint8_t flag; 1922cc290419Sopenharmony_ci string msg; 1923cc290419Sopenharmony_ci void *data; 1924cc290419Sopenharmony_ci std::function<void(const uint8_t, string &, const void *)> cb; 1925cc290419Sopenharmony_ci }; 1926cc290419Sopenharmony_ci auto funcDelayDo = [](uv_timer_t *handle) -> void { 1927cc290419Sopenharmony_ci DelayDoParam *st = (DelayDoParam *)handle->data; 1928cc290419Sopenharmony_ci st->cb(st->flag, st->msg, st->data); 1929cc290419Sopenharmony_ci uv_close((uv_handle_t *)handle, [](uv_handle_t *handle) { 1930cc290419Sopenharmony_ci DelayDoParam *st = (DelayDoParam *)handle->data; 1931cc290419Sopenharmony_ci delete st; 1932cc290419Sopenharmony_ci }); 1933cc290419Sopenharmony_ci }; 1934cc290419Sopenharmony_ci DelayDoParam *st = new(std::nothrow) DelayDoParam(); 1935cc290419Sopenharmony_ci if (st == nullptr) { 1936cc290419Sopenharmony_ci return false; 1937cc290419Sopenharmony_ci } 1938cc290419Sopenharmony_ci st->cb = cb; 1939cc290419Sopenharmony_ci st->flag = flag; 1940cc290419Sopenharmony_ci st->msg = msg; 1941cc290419Sopenharmony_ci st->data = data; 1942cc290419Sopenharmony_ci st->handle.data = st; 1943cc290419Sopenharmony_ci uv_timer_init(loop, &st->handle); 1944cc290419Sopenharmony_ci uv_timer_start(&st->handle, funcDelayDo, delayMs, 0); 1945cc290419Sopenharmony_ci return true; 1946cc290419Sopenharmony_ci } 1947cc290419Sopenharmony_ci 1948cc290419Sopenharmony_ci string ReplaceAll(string str, const string from, const string to) 1949cc290419Sopenharmony_ci { 1950cc290419Sopenharmony_ci string::size_type startPos = 0; 1951cc290419Sopenharmony_ci while ((startPos = str.find(from, startPos)) != string::npos) { 1952cc290419Sopenharmony_ci str.replace(startPos, from.length(), to); 1953cc290419Sopenharmony_ci startPos += to.length(); // Handles case where 'to' is a substring of 'from' 1954cc290419Sopenharmony_ci } 1955cc290419Sopenharmony_ci return str; 1956cc290419Sopenharmony_ci } 1957cc290419Sopenharmony_ci 1958cc290419Sopenharmony_ci string CanonicalizeSpecPath(string &src) 1959cc290419Sopenharmony_ci { 1960cc290419Sopenharmony_ci char resolvedPath[PATH_MAX] = { 0 }; 1961cc290419Sopenharmony_ci#if defined(_WIN32) 1962cc290419Sopenharmony_ci if (!_fullpath(resolvedPath, src.c_str(), PATH_MAX)) { 1963cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "_fullpath %s failed", src.c_str()); 1964cc290419Sopenharmony_ci return ""; 1965cc290419Sopenharmony_ci } 1966cc290419Sopenharmony_ci#else 1967cc290419Sopenharmony_ci if (realpath(src.c_str(), resolvedPath) == nullptr) { 1968cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "realpath %s failed", src.c_str()); 1969cc290419Sopenharmony_ci return ""; 1970cc290419Sopenharmony_ci } 1971cc290419Sopenharmony_ci#endif 1972cc290419Sopenharmony_ci string res(resolvedPath); 1973cc290419Sopenharmony_ci return res; 1974cc290419Sopenharmony_ci } 1975cc290419Sopenharmony_ci 1976cc290419Sopenharmony_ci string UnicodeToUtf8(const char *src, bool reverse) 1977cc290419Sopenharmony_ci { 1978cc290419Sopenharmony_ci#if defined(_WIN32) 1979cc290419Sopenharmony_ci UINT from = CP_ACP; 1980cc290419Sopenharmony_ci UINT to = CP_UTF8; 1981cc290419Sopenharmony_ci int count = 0; 1982cc290419Sopenharmony_ci if (reverse) { 1983cc290419Sopenharmony_ci from = CP_UTF8; 1984cc290419Sopenharmony_ci to = CP_ACP; 1985cc290419Sopenharmony_ci } 1986cc290419Sopenharmony_ci count = MultiByteToWideChar(from, 0, src, -1, nullptr, 0); 1987cc290419Sopenharmony_ci if (count <= 0) { 1988cc290419Sopenharmony_ci DWORD err = GetLastError(); 1989cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "MultiByteToWideChar failed %s error:%lu", src, err); 1990cc290419Sopenharmony_ci return ""; 1991cc290419Sopenharmony_ci } 1992cc290419Sopenharmony_ci wchar_t *wstr = new(std::nothrow) wchar_t[count + 1](); 1993cc290419Sopenharmony_ci if (wstr == nullptr) { 1994cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "new wstr failed count:%d", count); 1995cc290419Sopenharmony_ci return ""; 1996cc290419Sopenharmony_ci } 1997cc290419Sopenharmony_ci count = MultiByteToWideChar(from, 0, src, -1, wstr, count); 1998cc290419Sopenharmony_ci if (count <= 0) { 1999cc290419Sopenharmony_ci DWORD err = GetLastError(); 2000cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "MultiByteToWideChar failed to wstr %s error:%lu", src, err); 2001cc290419Sopenharmony_ci delete[] wstr; 2002cc290419Sopenharmony_ci return ""; 2003cc290419Sopenharmony_ci } 2004cc290419Sopenharmony_ci count = WideCharToMultiByte(to, 0, wstr, -1, nullptr, 0, nullptr, nullptr); 2005cc290419Sopenharmony_ci if (count <= 0) { 2006cc290419Sopenharmony_ci DWORD err = GetLastError(); 2007cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "WideCharToMultiByte failed %s error:%lu", wstr, err); 2008cc290419Sopenharmony_ci delete[] wstr; 2009cc290419Sopenharmony_ci return ""; 2010cc290419Sopenharmony_ci } 2011cc290419Sopenharmony_ci char *ustr = new(std::nothrow) char[count + 1](); 2012cc290419Sopenharmony_ci if (ustr == nullptr) { 2013cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "new ustr failed count:%d", count); 2014cc290419Sopenharmony_ci delete[] wstr; 2015cc290419Sopenharmony_ci return ""; 2016cc290419Sopenharmony_ci } 2017cc290419Sopenharmony_ci count = WideCharToMultiByte(to, 0, wstr, -1, ustr, count, nullptr, nullptr); 2018cc290419Sopenharmony_ci if (count <= 0) { 2019cc290419Sopenharmony_ci DWORD err = GetLastError(); 2020cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "WideCharToMultiByte failed to ustr %s error:%lu", wstr, err); 2021cc290419Sopenharmony_ci delete[] wstr; 2022cc290419Sopenharmony_ci delete[] ustr; 2023cc290419Sopenharmony_ci return ""; 2024cc290419Sopenharmony_ci } 2025cc290419Sopenharmony_ci string rc(ustr); 2026cc290419Sopenharmony_ci delete[] wstr; 2027cc290419Sopenharmony_ci delete[] ustr; 2028cc290419Sopenharmony_ci return rc; 2029cc290419Sopenharmony_ci#else 2030cc290419Sopenharmony_ci string rc(src); 2031cc290419Sopenharmony_ci return rc; 2032cc290419Sopenharmony_ci#endif 2033cc290419Sopenharmony_ci } 2034cc290419Sopenharmony_ci 2035cc290419Sopenharmony_ci uint8_t CalcCheckSum(const uint8_t *data, int len) 2036cc290419Sopenharmony_ci { 2037cc290419Sopenharmony_ci uint8_t ret = 0; 2038cc290419Sopenharmony_ci for (int i = 0; i < len; ++i) { 2039cc290419Sopenharmony_ci ret += data[i]; 2040cc290419Sopenharmony_ci } 2041cc290419Sopenharmony_ci return ret; 2042cc290419Sopenharmony_ci } 2043cc290419Sopenharmony_ci 2044cc290419Sopenharmony_ci uv_os_sock_t DuplicateUvSocket(uv_tcp_t *tcp) 2045cc290419Sopenharmony_ci { 2046cc290419Sopenharmony_ci uv_os_sock_t dupFd = -1; 2047cc290419Sopenharmony_ci#ifdef _WIN32 2048cc290419Sopenharmony_ci WSAPROTOCOL_INFO info; 2049cc290419Sopenharmony_ci ZeroStruct(info); 2050cc290419Sopenharmony_ci if (WSADuplicateSocketA(tcp->socket, GetCurrentProcessId(), &info) < 0) { 2051cc290419Sopenharmony_ci return dupFd; 2052cc290419Sopenharmony_ci } 2053cc290419Sopenharmony_ci dupFd = WSASocketA(0, 0, 0, &info, 0, 0); 2054cc290419Sopenharmony_ci#else 2055cc290419Sopenharmony_ci uv_os_fd_t fdOs; 2056cc290419Sopenharmony_ci if (uv_fileno((const uv_handle_t *)tcp, &fdOs) < 0) { 2057cc290419Sopenharmony_ci return ERR_API_FAIL; 2058cc290419Sopenharmony_ci } 2059cc290419Sopenharmony_ci#ifdef HDC_HOST 2060cc290419Sopenharmony_ci dupFd = dup(uv_open_osfhandle(fdOs)); 2061cc290419Sopenharmony_ci#else 2062cc290419Sopenharmony_ci dupFd = fcntl(uv_open_osfhandle(fdOs), F_DUPFD_CLOEXEC, uv_open_osfhandle(fdOs)); 2063cc290419Sopenharmony_ci#endif // HDC_HOST 2064cc290419Sopenharmony_ci#endif 2065cc290419Sopenharmony_ci return dupFd; 2066cc290419Sopenharmony_ci } 2067cc290419Sopenharmony_ci 2068cc290419Sopenharmony_ci string GetCwd() 2069cc290419Sopenharmony_ci { 2070cc290419Sopenharmony_ci int value = -1; 2071cc290419Sopenharmony_ci char path[PATH_MAX] = ""; 2072cc290419Sopenharmony_ci size_t size = sizeof(path); 2073cc290419Sopenharmony_ci string res; 2074cc290419Sopenharmony_ci value = uv_cwd(path, &size); 2075cc290419Sopenharmony_ci if (value < 0) { 2076cc290419Sopenharmony_ci constexpr int bufSize = 1024; 2077cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 2078cc290419Sopenharmony_ci uv_strerror_r(value, buf, bufSize); 2079cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "get path failed: %s", buf); 2080cc290419Sopenharmony_ci return res; 2081cc290419Sopenharmony_ci } 2082cc290419Sopenharmony_ci size_t len = 0; 2083cc290419Sopenharmony_ci len = strlen(path); 2084cc290419Sopenharmony_ci if (len < 1 || len >= PATH_MAX - 1) { 2085cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "get path failed: buffer space max"); 2086cc290419Sopenharmony_ci return res; 2087cc290419Sopenharmony_ci } 2088cc290419Sopenharmony_ci if (path[len - 1] != Base::GetPathSep()) { 2089cc290419Sopenharmony_ci path[len] = Base::GetPathSep(); 2090cc290419Sopenharmony_ci } 2091cc290419Sopenharmony_ci res = path; 2092cc290419Sopenharmony_ci return res; 2093cc290419Sopenharmony_ci } 2094cc290419Sopenharmony_ci 2095cc290419Sopenharmony_ci string GetTmpDir() 2096cc290419Sopenharmony_ci { 2097cc290419Sopenharmony_ci string res; 2098cc290419Sopenharmony_ci#ifdef HDC_HOST 2099cc290419Sopenharmony_ci int value = -1; 2100cc290419Sopenharmony_ci char path[PATH_MAX] = ""; 2101cc290419Sopenharmony_ci size_t size = sizeof(path); 2102cc290419Sopenharmony_ci value = uv_os_tmpdir(path, &size); 2103cc290419Sopenharmony_ci if (value < 0) { 2104cc290419Sopenharmony_ci constexpr int bufSize = 1024; 2105cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 2106cc290419Sopenharmony_ci uv_strerror_r(value, buf, bufSize); 2107cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "get tmppath failed: %s", buf); 2108cc290419Sopenharmony_ci return res; 2109cc290419Sopenharmony_ci } 2110cc290419Sopenharmony_ci if (strlen(path) >= PATH_MAX - 1) { 2111cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "get tmppath failed: buffer space max"); 2112cc290419Sopenharmony_ci return res; 2113cc290419Sopenharmony_ci } 2114cc290419Sopenharmony_ci if (path[strlen(path) - 1] != Base::GetPathSep()) { 2115cc290419Sopenharmony_ci path[strlen(path)] = Base::GetPathSep(); 2116cc290419Sopenharmony_ci } 2117cc290419Sopenharmony_ci res = path; 2118cc290419Sopenharmony_ci#else 2119cc290419Sopenharmony_ci res = "/data/local/tmp/"; 2120cc290419Sopenharmony_ci#endif 2121cc290419Sopenharmony_ci return res; 2122cc290419Sopenharmony_ci } 2123cc290419Sopenharmony_ci 2124cc290419Sopenharmony_ci#ifndef HDC_HILOG 2125cc290419Sopenharmony_ci void SetLogCache(bool enable) 2126cc290419Sopenharmony_ci { 2127cc290419Sopenharmony_ci g_logCache = enable; 2128cc290419Sopenharmony_ci } 2129cc290419Sopenharmony_ci 2130cc290419Sopenharmony_ci void RemoveLogFile() 2131cc290419Sopenharmony_ci { 2132cc290419Sopenharmony_ci if (g_logCache) { 2133cc290419Sopenharmony_ci string path = GetLogDirName() + LOG_FILE_NAME; 2134cc290419Sopenharmony_ci string bakName = GetLogNameWithTime(); 2135cc290419Sopenharmony_ci string bakPath = GetLogDirName() + bakName; 2136cc290419Sopenharmony_ci string cachePath = GetLogDirName() + LOG_CACHE_NAME; 2137cc290419Sopenharmony_ci if (rename(path.c_str(), bakPath.c_str()) != 0) { 2138cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "rename log file failed."); 2139cc290419Sopenharmony_ci } 2140cc290419Sopenharmony_ci if (rename(cachePath.c_str(), path.c_str()) != 0) { 2141cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "rename log cache file failed."); 2142cc290419Sopenharmony_ci } 2143cc290419Sopenharmony_ci std::thread compressThread(ThreadCompressLog, bakName); 2144cc290419Sopenharmony_ci compressThread.detach(); 2145cc290419Sopenharmony_ci g_logCache = false; 2146cc290419Sopenharmony_ci std::thread removeThread(RemoveOlderLogFiles); 2147cc290419Sopenharmony_ci removeThread.detach(); 2148cc290419Sopenharmony_ci } 2149cc290419Sopenharmony_ci } 2150cc290419Sopenharmony_ci 2151cc290419Sopenharmony_ci void RemoveLogCache() 2152cc290419Sopenharmony_ci { 2153cc290419Sopenharmony_ci string cachePath = GetLogDirName() + LOG_CACHE_NAME; 2154cc290419Sopenharmony_ci unlink(cachePath.c_str()); 2155cc290419Sopenharmony_ci } 2156cc290419Sopenharmony_ci#endif 2157cc290419Sopenharmony_ci 2158cc290419Sopenharmony_ci bool IsRoot() 2159cc290419Sopenharmony_ci { 2160cc290419Sopenharmony_ci#ifdef _WIN32 2161cc290419Sopenharmony_ci // reserve 2162cc290419Sopenharmony_ci return true; 2163cc290419Sopenharmony_ci#else 2164cc290419Sopenharmony_ci if (getuid() == 0) { 2165cc290419Sopenharmony_ci return true; 2166cc290419Sopenharmony_ci } 2167cc290419Sopenharmony_ci#endif 2168cc290419Sopenharmony_ci return false; 2169cc290419Sopenharmony_ci } 2170cc290419Sopenharmony_ci 2171cc290419Sopenharmony_ci bool IsAbsolutePath(string &path) 2172cc290419Sopenharmony_ci { 2173cc290419Sopenharmony_ci bool ret = false; 2174cc290419Sopenharmony_ci#ifdef _WIN32 2175cc290419Sopenharmony_ci // shlwapi.h PathIsRelativeA not link in harmony project 2176cc290419Sopenharmony_ci // c:\ or UNC path '\\hostname\share\file' 2177cc290419Sopenharmony_ci ret = path.find(":\\") == 1 || path.find("\\\\") == 0; 2178cc290419Sopenharmony_ci#else 2179cc290419Sopenharmony_ci ret = path[0] == '/'; 2180cc290419Sopenharmony_ci#endif 2181cc290419Sopenharmony_ci return ret; 2182cc290419Sopenharmony_ci } 2183cc290419Sopenharmony_ci 2184cc290419Sopenharmony_ci int CloseFd(int &fd) 2185cc290419Sopenharmony_ci { 2186cc290419Sopenharmony_ci int rc = 0; 2187cc290419Sopenharmony_ci if (fd > 0) { 2188cc290419Sopenharmony_ci rc = close(fd); 2189cc290419Sopenharmony_ci if (rc < 0) { 2190cc290419Sopenharmony_ci char buffer[BUF_SIZE_DEFAULT] = { 0 }; 2191cc290419Sopenharmony_ci#ifdef _WIN32 2192cc290419Sopenharmony_ci strerror_s(buffer, BUF_SIZE_DEFAULT, errno); 2193cc290419Sopenharmony_ci#else 2194cc290419Sopenharmony_ci strerror_r(errno, buffer, BUF_SIZE_DEFAULT); 2195cc290419Sopenharmony_ci#endif 2196cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "close fd: %d failed errno:%d %s", fd, errno, buffer); 2197cc290419Sopenharmony_ci } else { 2198cc290419Sopenharmony_ci fd = -1; 2199cc290419Sopenharmony_ci } 2200cc290419Sopenharmony_ci } 2201cc290419Sopenharmony_ci return rc; 2202cc290419Sopenharmony_ci } 2203cc290419Sopenharmony_ci 2204cc290419Sopenharmony_ci void InitProcess(void) 2205cc290419Sopenharmony_ci { 2206cc290419Sopenharmony_ci#ifndef _WIN32 2207cc290419Sopenharmony_ci umask(0); 2208cc290419Sopenharmony_ci signal(SIGPIPE, SIG_IGN); 2209cc290419Sopenharmony_ci signal(SIGCHLD, SIG_IGN); 2210cc290419Sopenharmony_ci signal(SIGALRM, SIG_IGN); 2211cc290419Sopenharmony_ci signal(SIGTTIN, SIG_IGN); 2212cc290419Sopenharmony_ci signal(SIGTTOU, SIG_IGN); 2213cc290419Sopenharmony_ci sigemptyset(&g_blockList); 2214cc290419Sopenharmony_ci constexpr int crashSignal = 35; 2215cc290419Sopenharmony_ci sigaddset(&g_blockList, crashSignal); 2216cc290419Sopenharmony_ci sigprocmask(SIG_BLOCK, &g_blockList, nullptr); 2217cc290419Sopenharmony_ci#endif 2218cc290419Sopenharmony_ci } 2219cc290419Sopenharmony_ci 2220cc290419Sopenharmony_ci void DeInitProcess(void) 2221cc290419Sopenharmony_ci { 2222cc290419Sopenharmony_ci#ifndef _WIN32 2223cc290419Sopenharmony_ci mode_t writePermission = 022; 2224cc290419Sopenharmony_ci umask(writePermission); 2225cc290419Sopenharmony_ci signal(SIGPIPE, SIG_DFL); 2226cc290419Sopenharmony_ci signal(SIGCHLD, SIG_DFL); 2227cc290419Sopenharmony_ci signal(SIGALRM, SIG_DFL); 2228cc290419Sopenharmony_ci signal(SIGTTIN, SIG_DFL); 2229cc290419Sopenharmony_ci signal(SIGTTOU, SIG_DFL); 2230cc290419Sopenharmony_ci#endif 2231cc290419Sopenharmony_ci } 2232cc290419Sopenharmony_ci 2233cc290419Sopenharmony_ci int ReadFromFd(int fd, void *buf, size_t count) 2234cc290419Sopenharmony_ci { 2235cc290419Sopenharmony_ci#ifdef _WIN32 2236cc290419Sopenharmony_ci DWORD bytesRead = 0; 2237cc290419Sopenharmony_ci OVERLAPPED ov = {}; 2238cc290419Sopenharmony_ci SOCKET s = fd; 2239cc290419Sopenharmony_ci BOOL bWriteStat = ReadFile((HANDLE)s, buf, count, &bytesRead, &ov); 2240cc290419Sopenharmony_ci if (bWriteStat) { 2241cc290419Sopenharmony_ci return bytesRead; 2242cc290419Sopenharmony_ci } else { 2243cc290419Sopenharmony_ci return -1; 2244cc290419Sopenharmony_ci } 2245cc290419Sopenharmony_ci#else 2246cc290419Sopenharmony_ci return TEMP_FAILURE_RETRY(read(fd, buf, count)); 2247cc290419Sopenharmony_ci#endif 2248cc290419Sopenharmony_ci } 2249cc290419Sopenharmony_ci 2250cc290419Sopenharmony_ci int WriteToFd(int fd, const void *buf, size_t count) 2251cc290419Sopenharmony_ci { 2252cc290419Sopenharmony_ci#ifdef _WIN32 2253cc290419Sopenharmony_ci DWORD bytesWrite = 0; 2254cc290419Sopenharmony_ci OVERLAPPED ov = {}; 2255cc290419Sopenharmony_ci SOCKET s = fd; 2256cc290419Sopenharmony_ci BOOL bWriteStat = WriteFile((HANDLE)s, buf, count, &bytesWrite, &ov); 2257cc290419Sopenharmony_ci if (bWriteStat) { 2258cc290419Sopenharmony_ci return 1; 2259cc290419Sopenharmony_ci } else { 2260cc290419Sopenharmony_ci return -1; 2261cc290419Sopenharmony_ci } 2262cc290419Sopenharmony_ci#else 2263cc290419Sopenharmony_ci return TEMP_FAILURE_RETRY(write(fd, buf, count)); 2264cc290419Sopenharmony_ci#endif 2265cc290419Sopenharmony_ci } 2266cc290419Sopenharmony_ci 2267cc290419Sopenharmony_ci bool IsValidIpv4(const std::string& ip) 2268cc290419Sopenharmony_ci { 2269cc290419Sopenharmony_ci std::vector<int> segments; 2270cc290419Sopenharmony_ci std::stringstream ss(ip); 2271cc290419Sopenharmony_ci std::string segment; 2272cc290419Sopenharmony_ci const int ipCount = 4; 2273cc290419Sopenharmony_ci const int maxValue = 255; 2274cc290419Sopenharmony_ci 2275cc290419Sopenharmony_ci // 分解字符串为四部分 2276cc290419Sopenharmony_ci while (std::getline(ss, segment, '.')) { 2277cc290419Sopenharmony_ci if (segments.size() >= ipCount) { 2278cc290419Sopenharmony_ci return false; 2279cc290419Sopenharmony_ci } 2280cc290419Sopenharmony_ci if (!IsDigitString(segment)) { 2281cc290419Sopenharmony_ci return false; 2282cc290419Sopenharmony_ci } 2283cc290419Sopenharmony_ci int num = std::stoi(segment); 2284cc290419Sopenharmony_ci if (num < 0 || num > maxValue) { 2285cc290419Sopenharmony_ci return false; 2286cc290419Sopenharmony_ci } 2287cc290419Sopenharmony_ci if (segment.size() > 1 && segment[0] == '0' && segment != "0") { 2288cc290419Sopenharmony_ci return false; 2289cc290419Sopenharmony_ci } 2290cc290419Sopenharmony_ci segments.push_back(num); 2291cc290419Sopenharmony_ci } 2292cc290419Sopenharmony_ci // 必须正好有四部分 2293cc290419Sopenharmony_ci return segments.size() == ipCount; 2294cc290419Sopenharmony_ci } 2295cc290419Sopenharmony_ci 2296cc290419Sopenharmony_ci // Trim from both sides and paired 2297cc290419Sopenharmony_ci string &ShellCmdTrim(string &cmd) 2298cc290419Sopenharmony_ci { 2299cc290419Sopenharmony_ci const string pairedQuot("\"\""); 2300cc290419Sopenharmony_ci if (cmd.empty()) { 2301cc290419Sopenharmony_ci return cmd; 2302cc290419Sopenharmony_ci } 2303cc290419Sopenharmony_ci cmd = Trim(cmd); 2304cc290419Sopenharmony_ci if (cmd.length() < pairedQuot.length()) { 2305cc290419Sopenharmony_ci return cmd; 2306cc290419Sopenharmony_ci } 2307cc290419Sopenharmony_ci if (*cmd.begin() == '"' && cmd.back() == '"') { 2308cc290419Sopenharmony_ci cmd.erase(cmd.begin()); 2309cc290419Sopenharmony_ci cmd.pop_back(); 2310cc290419Sopenharmony_ci } 2311cc290419Sopenharmony_ci return cmd; 2312cc290419Sopenharmony_ci } 2313cc290419Sopenharmony_ci 2314cc290419Sopenharmony_ci void TrimSubString(string &str, string substr) 2315cc290419Sopenharmony_ci { 2316cc290419Sopenharmony_ci std::string::size_type pos = 0; 2317cc290419Sopenharmony_ci while ((pos = str.find(substr, pos)) != std::string::npos) { 2318cc290419Sopenharmony_ci str.erase(pos, substr.length()); 2319cc290419Sopenharmony_ci } 2320cc290419Sopenharmony_ci } 2321cc290419Sopenharmony_ci // first 16 bytes is tag 2322cc290419Sopenharmony_ci // second 16 bytes is length 2323cc290419Sopenharmony_ci // flow the value 2324cc290419Sopenharmony_ci bool TlvAppend(string &tlv, string tag, string val) 2325cc290419Sopenharmony_ci { 2326cc290419Sopenharmony_ci if (tag.empty()) { 2327cc290419Sopenharmony_ci return false; 2328cc290419Sopenharmony_ci } 2329cc290419Sopenharmony_ci unsigned int tlen = tag.length(); 2330cc290419Sopenharmony_ci if (tlen < TLV_TAG_LEN) { 2331cc290419Sopenharmony_ci tag.append(TLV_TAG_LEN - tlen, ' '); 2332cc290419Sopenharmony_ci } 2333cc290419Sopenharmony_ci tlv.append(tag); 2334cc290419Sopenharmony_ci string vallen = std::to_string(val.length()); 2335cc290419Sopenharmony_ci unsigned int vlen = vallen.length(); 2336cc290419Sopenharmony_ci if (vlen < TLV_VAL_LEN) { 2337cc290419Sopenharmony_ci vallen.append(TLV_VAL_LEN - vlen, ' '); 2338cc290419Sopenharmony_ci } 2339cc290419Sopenharmony_ci tlv.append(vallen); 2340cc290419Sopenharmony_ci tlv.append(val); 2341cc290419Sopenharmony_ci return true; 2342cc290419Sopenharmony_ci } 2343cc290419Sopenharmony_ci bool TlvToStringMap(string tlv, std::map<string, string> &tlvmap) 2344cc290419Sopenharmony_ci { 2345cc290419Sopenharmony_ci if (tlv.length() < TLV_MIN_LEN) { 2346cc290419Sopenharmony_ci return false; 2347cc290419Sopenharmony_ci } 2348cc290419Sopenharmony_ci while (tlv.length() >= TLV_MIN_LEN) { 2349cc290419Sopenharmony_ci string tag = tlv.substr(0, TLV_TAG_LEN); 2350cc290419Sopenharmony_ci TrimSubString(tag, " "); 2351cc290419Sopenharmony_ci tlv.erase(0, TLV_TAG_LEN); 2352cc290419Sopenharmony_ci 2353cc290419Sopenharmony_ci string vallen = tlv.substr(0, TLV_VAL_LEN); 2354cc290419Sopenharmony_ci TrimSubString(vallen, " "); 2355cc290419Sopenharmony_ci int len = atoi(vallen.c_str()); 2356cc290419Sopenharmony_ci if (len < 0) { 2357cc290419Sopenharmony_ci return false; 2358cc290419Sopenharmony_ci } 2359cc290419Sopenharmony_ci tlv.erase(0, TLV_VAL_LEN); 2360cc290419Sopenharmony_ci 2361cc290419Sopenharmony_ci if (tlv.length() < static_cast<uint32_t>(len)) { 2362cc290419Sopenharmony_ci return false; 2363cc290419Sopenharmony_ci } 2364cc290419Sopenharmony_ci string val = tlv.substr(0, len); 2365cc290419Sopenharmony_ci tlv.erase(0, len); 2366cc290419Sopenharmony_ci 2367cc290419Sopenharmony_ci tlvmap[tag] = val; 2368cc290419Sopenharmony_ci } 2369cc290419Sopenharmony_ci return true; 2370cc290419Sopenharmony_ci } 2371cc290419Sopenharmony_ci 2372cc290419Sopenharmony_ci // NOTE: This function relies on the caller to guarantee that 2373cc290419Sopenharmony_ci // the input parameter is not null and to check the opened handle state. 2374cc290419Sopenharmony_ci FILE *Fopen(const char *fileName, const char *mode) 2375cc290419Sopenharmony_ci { 2376cc290419Sopenharmony_ci#ifdef _WIN32 2377cc290419Sopenharmony_ci wchar_t resolvedPath[PATH_MAX + 1] = { 0 }; 2378cc290419Sopenharmony_ci // windows platform open file with wide char 2379cc290419Sopenharmony_ci std::wstring_convert<std::codecvt_utf8<wchar_t>> converter; 2380cc290419Sopenharmony_ci std::wstring wideFileName = converter.from_bytes(fileName); 2381cc290419Sopenharmony_ci std::wstring wideMode = converter.from_bytes(mode); 2382cc290419Sopenharmony_ci if (!_wfullpath(resolvedPath, wideFileName.c_str(), PATH_MAX + 1)) { 2383cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "_wfullpath %s failed", wideFileName.c_str()); 2384cc290419Sopenharmony_ci return nullptr; 2385cc290419Sopenharmony_ci } 2386cc290419Sopenharmony_ci return _wfopen(resolvedPath, wideMode.c_str()); 2387cc290419Sopenharmony_ci#else 2388cc290419Sopenharmony_ci // unix paltform open file with default char 2389cc290419Sopenharmony_ci return fopen(fileName, mode); 2390cc290419Sopenharmony_ci#endif 2391cc290419Sopenharmony_ci } 2392cc290419Sopenharmony_ci 2393cc290419Sopenharmony_ci std::set<uint32_t> g_deletedSessionIdSet; 2394cc290419Sopenharmony_ci std::queue<uint32_t> g_deletedSessionIdQueue; 2395cc290419Sopenharmony_ci std::mutex g_deletedSessionIdRecordMutex; 2396cc290419Sopenharmony_ci void AddDeletedSessionId(uint32_t sessionId) 2397cc290419Sopenharmony_ci { 2398cc290419Sopenharmony_ci std::lock_guard<std::mutex> lock(g_deletedSessionIdRecordMutex); 2399cc290419Sopenharmony_ci if (g_deletedSessionIdSet.find(sessionId) != g_deletedSessionIdSet.end()) { 2400cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "SessionId:%u is already in the cache", sessionId); 2401cc290419Sopenharmony_ci return; 2402cc290419Sopenharmony_ci } 2403cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "AddDeletedSessionId:%u", sessionId); 2404cc290419Sopenharmony_ci g_deletedSessionIdSet.insert(sessionId); 2405cc290419Sopenharmony_ci g_deletedSessionIdQueue.push(sessionId); 2406cc290419Sopenharmony_ci 2407cc290419Sopenharmony_ci // Delete old records and only save MAX_DELETED_SESSION_ID_RECORD_COUNT records 2408cc290419Sopenharmony_ci if (g_deletedSessionIdQueue.size() > MAX_DELETED_SESSION_ID_RECORD_COUNT) { 2409cc290419Sopenharmony_ci uint32_t id = g_deletedSessionIdQueue.front(); 2410cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "g_deletedSessionIdQueue size:%u, g_deletedSessionIdSet size:%u, pop session id:%u", 2411cc290419Sopenharmony_ci g_deletedSessionIdQueue.size(), g_deletedSessionIdSet.size(), id); 2412cc290419Sopenharmony_ci g_deletedSessionIdQueue.pop(); 2413cc290419Sopenharmony_ci g_deletedSessionIdSet.erase(id); 2414cc290419Sopenharmony_ci } 2415cc290419Sopenharmony_ci } 2416cc290419Sopenharmony_ci 2417cc290419Sopenharmony_ci bool IsSessionDeleted(uint32_t sessionId) 2418cc290419Sopenharmony_ci { 2419cc290419Sopenharmony_ci std::lock_guard<std::mutex> lock(g_deletedSessionIdRecordMutex); 2420cc290419Sopenharmony_ci if (g_deletedSessionIdSet.find(sessionId) != g_deletedSessionIdSet.end()) { 2421cc290419Sopenharmony_ci return true; 2422cc290419Sopenharmony_ci } 2423cc290419Sopenharmony_ci return false; 2424cc290419Sopenharmony_ci } 2425cc290419Sopenharmony_ci} 2426cc290419Sopenharmony_ci} // namespace Hdc 2427