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, &times);
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