Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "trace_system_api.h"
12 : #include "adiag_print.h"
13 : #include "adiag_utils.h"
14 : #include "trace_types.h"
15 :
16 : STATIC int32_t g_timeDst; // daylight saving time
17 :
18 2082 : void* TraceDlopen(const char* libPath, int32_t mode) { return mmDlopen(libPath, mode); }
19 :
20 4164 : void* TraceDlsym(void* handle, const char* funcName) { return mmDlsym(handle, funcName); }
21 :
22 2050 : int32_t TraceDlclose(void* handle) { return mmDlclose(handle); }
23 :
24 4755 : int32_t TraceGetPid(void) { return mmGetPid(); }
25 :
26 65 : int32_t TraceRaise(int32_t signo)
27 : {
28 : #if defined _ADIAG_LLT_
29 65 : return 0;
30 : #else
31 0 : return raise(signo);
32 : #endif
33 : }
34 :
35 8276 : int32_t TraceChmod(const char* dirPath, uint32_t mode) { return chmod(dirPath, mode); }
36 :
37 8264 : int32_t TraceChown(const char* dirPath, uint32_t uid, uint32_t gid) { return chown(dirPath, uid, gid); }
38 :
39 21084 : TraStatus TraceMkdir(const char* dirPath, uint32_t mode, uint32_t uid, uint32_t gid)
40 : {
41 21084 : ADIAG_CHK_NULL_PTR(dirPath, return TRACE_INVALID_PTR);
42 :
43 21084 : if (access(dirPath, F_OK) != 0) {
44 8374 : if (mkdir(dirPath, mode) != 0 && errno != EEXIST) {
45 110 : return TRACE_MKDIR_FAIL;
46 : }
47 8264 : if (TraceChmod(dirPath, mode) != 0) {
48 0 : return TRACE_CHMOD_FAIL;
49 : }
50 8264 : if (TraceChown(dirPath, uid, gid) != 0) {
51 0 : return TRACE_CHOWN_FAIL;
52 : }
53 : }
54 :
55 20974 : return TRACE_SUCCESS;
56 : }
57 :
58 2046 : int32_t TraceRmdir(const char* pathName) { return mmRmdir(pathName); }
59 :
60 4277 : int32_t TraceOpen(const char* filePath, int32_t flag, uint32_t mode)
61 : {
62 4277 : int32_t fd = open(filePath, flag, mode);
63 4277 : if (fd >= 0) {
64 4277 : (void)fchmod(fd, mode);
65 : }
66 4277 : return fd;
67 : }
68 :
69 2216 : void TraceClose(int32_t* fd)
70 : {
71 2216 : if ((fd == NULL) || (*fd < 0)) {
72 185 : return;
73 : }
74 :
75 2031 : (void)close(*fd);
76 2031 : *fd = -1;
77 : }
78 :
79 : /**
80 : * @brief get string of env
81 : * @param[in] env: environment value obtained from the environment variable
82 : * @param[out] buf: buffer to save string
83 : * @param[in] len: buffer length
84 : * @return TraStatus
85 : */
86 3469 : TraStatus TraceHandleEnvString(const char* env, char* buf, uint32_t len)
87 : {
88 3469 : ADIAG_CHK_NULL_PTR(buf, return TRACE_FAILURE);
89 3469 : if ((env == NULL) || (strlen(env) == 0U) || (strlen(env) > (size_t)len)) {
90 1795 : ADIAG_WAR("Environment variable is null or the length exceeds %u.", len);
91 1795 : return TRACE_FAILURE;
92 : }
93 :
94 1674 : int32_t ret = strcpy_s(buf, (size_t)len, env);
95 1674 : ADIAG_CHK_EXPR_ACTION(
96 : ret != EOK, return TRACE_FAILURE, "strcpy env string failed, ret=%d, strerr=%s.", ret,
97 : strerror(AdiagGetErrorCode()));
98 1674 : return TRACE_SUCCESS;
99 : }
100 :
101 12987 : int32_t TraceRealPath(const char* path, char* realPath, int32_t realPathLen)
102 : {
103 12987 : return mmRealPath(path, realPath, realPathLen);
104 : }
105 :
106 3106 : int32_t TraceAccess(const char* path, int32_t mode) { return mmAccess2(path, mode); }
107 :
108 280 : int32_t TraceCreateTaskWithThreadAttr(
109 : TraceThread* threadHandle, const TraceUserBlock* funcBlock, const TraceThreadAttr* threadAttr)
110 : {
111 280 : return mmCreateTaskWithThreadAttr(threadHandle, funcBlock, threadAttr);
112 : }
113 :
114 265 : int32_t TraceJoinTask(TraceThread* threadHandle) { return mmJoinTask(threadHandle); }
115 :
116 273 : int32_t TraceSetThreadName(const char* threadName) { return mmSetCurrentThreadName(threadName); }
117 :
118 4164 : int32_t TraceGetTimeOfDay(TraceTimeVal* timeVal, TraceTimeZone* timeZone) { return mmGetTimeOfDay(timeVal, timeZone); }
119 :
120 2038 : int32_t TraceLocalTimeR(const time_t* timep, struct tm* result) { return mmLocalTimeR(timep, result); }
121 :
122 31 : int32_t TraceSocket(int32_t sockFamily, int32_t type, int32_t protocol) { return mmSocket(sockFamily, type, protocol); }
123 :
124 13 : int32_t TraceBind(int32_t sockFd, TraceSockAddr* addr, size_t addrLen)
125 : {
126 13 : return mmBind((mmSockHandle)sockFd, (mmSockAddr*)addr, (mmSocklen_t)addrLen);
127 : }
128 :
129 30 : int32_t TraceCloseSocket(int32_t sockFd) { return mmCloseSocket((mmSockHandle)sockFd); }
130 :
131 13 : int32_t TraceConnect(int32_t sockFd, struct sockaddr* addr, size_t addrLen)
132 : {
133 13 : return mmConnect((mmSockHandle)sockFd, (mmSockAddr*)addr, (mmSocklen_t)addrLen);
134 : }
135 :
136 20480312 : STATIC INLINE int32_t IsLeapYear(int32_t year)
137 : {
138 : // years can be divisible by 4, but not by 100, or years can be divisible by 400
139 20480312 : return ((((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0)) ? 1 : 0;
140 : }
141 :
142 : /**
143 : * @brief get local time string from timestamp, must be reentrant, cannot print msg
144 : * @param [out] timeInfo: local time struct
145 : * @param [in] sec: seconds from 1970/1/1
146 : * @param [in] timeZone: current time zone
147 : * @param [in] dst: daylight time
148 : * @return void
149 : */
150 353636 : STATIC void CalLocalTime(struct tm* timeInfo, time_t sec, time_t timeZone, int32_t dst)
151 : {
152 353636 : const time_t oneMin = 60; // 1m: 60s
153 353636 : const time_t oneHour = 3600; // 1h: 3600s
154 353636 : const time_t oneDay = 86400; // 24h: 86400s
155 353636 : const time_t oneYear = 365; // 365 days
156 :
157 353636 : time_t realSec = sec - timeZone; // Adjust for timezone
158 353636 : realSec += oneHour * dst; // Adjust for daylight time
159 353636 : time_t days = realSec / oneDay; // Days passed since epoch
160 353636 : time_t seconds = realSec % oneDay; // Remaining seconds
161 :
162 353636 : timeInfo->tm_isdst = dst;
163 353636 : timeInfo->tm_hour = (int32_t)(seconds / oneHour);
164 353636 : timeInfo->tm_min = (int32_t)((seconds % oneHour) / oneMin);
165 353636 : timeInfo->tm_sec = (int32_t)((seconds % oneHour) % oneMin);
166 :
167 : // 1/1/1970 was a Thursday, that is, day 4 from the POV of the tm structure * where sunday = 0,
168 : // so to calculate the day of the week we have to add 4 * and take the modulo by 7.
169 353636 : timeInfo->tm_wday = (int32_t)((days + 4) % 7); // start from Thursday
170 : // Calculate the current year
171 353636 : timeInfo->tm_year = 1970; // start from 1970
172 19773040 : while (1) {
173 : // Leap years have one day more
174 20126676 : time_t yearDays = oneYear + (time_t)IsLeapYear(timeInfo->tm_year);
175 20126676 : if (yearDays > days) {
176 353636 : break;
177 : }
178 19773040 : days -= yearDays;
179 19773040 : timeInfo->tm_year++;
180 : }
181 353636 : timeInfo->tm_yday = (int32_t)days; // Number of day of the current year
182 :
183 : // We need to calculate in which month and day of the month we are. To do *,
184 : // so we need to skip days according to how many days there are in each * month,
185 : // and adjust for the leap year that has one more day in February.
186 353636 : int32_t mDays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // days of month: 31, 30, 28/29
187 353636 : mDays[1] += IsLeapYear(timeInfo->tm_year); // leap year
188 :
189 353636 : timeInfo->tm_mon = 0;
190 2825266 : while (days >= mDays[timeInfo->tm_mon]) {
191 2471630 : days -= mDays[timeInfo->tm_mon];
192 2471630 : timeInfo->tm_mon++;
193 : }
194 :
195 353636 : timeInfo->tm_mon++; // Add 1 since our 'month' is zero-based
196 353636 : timeInfo->tm_mday = (int32_t)days + 1; // Add 1 since our 'days' is zero-based
197 353636 : }
198 :
199 : /**
200 : * @brief init daylight saving time
201 : * @return TraStatus
202 : */
203 2082 : TraStatus TraceTimeDstInit(void)
204 : {
205 2082 : TraceTimeVal timeVal = {0, 0};
206 : struct tm tmInfo;
207 2082 : (void)memset_s(&tmInfo, sizeof(tmInfo), 0, sizeof(tmInfo));
208 : // sync time zone
209 2082 : tzset();
210 2082 : if (TraceGetTimeOfDay(&timeVal, NULL) != TRACE_SUCCESS) {
211 44 : ADIAG_ERR("get time of day failed, errno=%s.", strerror(AdiagGetErrorCode()));
212 44 : return TRACE_FAILURE;
213 : }
214 2038 : const time_t sec = timeVal.tv_sec;
215 2038 : if (TraceLocalTimeR(&sec, &tmInfo) != TRACE_SUCCESS) {
216 22 : ADIAG_ERR("get local time failed, errno=%s.", strerror(AdiagGetErrorCode()));
217 22 : return TRACE_FAILURE;
218 : }
219 :
220 2016 : g_timeDst = tmInfo.tm_isdst;
221 2016 : return TRACE_SUCCESS;
222 : }
223 :
224 : /**
225 : * @brief get local time string from timestamp, must be reentrant, cannot print msg
226 : * @param [in] timestamp: timestamp
227 : * @param [out] buffer: buffer to save timestamp str
228 : * @param [in] bufSize: size of buffer
229 : * @return TraStatus
230 : */
231 347719 : TraStatus TimestampToStr(uint64_t timestamp, char* buffer, uint32_t bufSize)
232 : {
233 347719 : uint64_t tmpTime = (timestamp / SEC_TO_NS) & (uint64_t)LONG_MAX;
234 347719 : time_t secTime = (time_t)tmpTime;
235 347719 : uint64_t microTime = timestamp % SEC_TO_NS;
236 : struct tm now;
237 347719 : CalLocalTime(&now, secTime, (time_t)timezone, g_timeDst);
238 :
239 347719 : int32_t err = sprintf_s(
240 : buffer, bufSize, "%04ld-%02d-%02d %02d:%02d:%02d.%03llu.%03llu ", now.tm_year, now.tm_mon, now.tm_mday,
241 : now.tm_hour, now.tm_min, now.tm_sec, (microTime / TIME_ONE_THOUSAND_MS) / TIME_ONE_THOUSAND_MS,
242 347719 : (microTime / TIME_ONE_THOUSAND_MS) % TIME_ONE_THOUSAND_MS);
243 347719 : if (err == -1) {
244 22 : return TRACE_RING_BUFFER_SPRINTF_FAILED;
245 : }
246 347697 : return TRACE_SUCCESS;
247 : }
248 :
249 : /**
250 : * @brief get local time string from timestamp, must be reentrant, cannot print msg
251 : * @param [in] timestamp: timestamp
252 : * @param [out] buffer: buffer to save timestamp str
253 : * @param [in] bufSize: size of buffer
254 : * @return TraStatus
255 : */
256 5917 : TraStatus TimestampToFileStr(uint64_t timestamp, char* buffer, uint32_t bufSize)
257 : {
258 5917 : uint64_t tmpTime = (timestamp / SEC_TO_NS) & (uint64_t)LONG_MAX;
259 5917 : time_t secTime = (time_t)tmpTime;
260 5917 : uint64_t microTime = timestamp % SEC_TO_NS;
261 : struct tm now;
262 5917 : CalLocalTime(&now, secTime, (time_t)timezone, g_timeDst);
263 :
264 5917 : int32_t err = sprintf_s(
265 : buffer, bufSize, "%04ld%02d%02d%02d%02d%02d%03llu%03llu", now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour,
266 : now.tm_min, now.tm_sec, (microTime / TIME_ONE_THOUSAND_MS) / TIME_ONE_THOUSAND_MS,
267 5917 : (microTime / TIME_ONE_THOUSAND_MS) % TIME_ONE_THOUSAND_MS);
268 5917 : if (err == -1) {
269 23 : return TRACE_RING_BUFFER_SPRINTF_FAILED;
270 : }
271 5894 : return TRACE_SUCCESS;
272 : }
273 :
274 : /**
275 : * @brief get the offset between local time and UTC
276 : * @param [out] offset: offset, unit:minute
277 : * @return TraStatus
278 : */
279 2082 : TraStatus TraceGetTimeOffset(int32_t* offset)
280 : {
281 2082 : TraceTimeVal tv = {0};
282 2082 : struct tm localTime = {0};
283 :
284 2082 : if (TraceGetTimeOfDay(&tv, NULL) != TRACE_SUCCESS) {
285 22 : return TRACE_FAILURE;
286 : }
287 2060 : time_t utcTime = tv.tv_sec;
288 2060 : if (localtime_r(&utcTime, &localTime) == NULL) {
289 22 : return TRACE_FAILURE;
290 : }
291 2038 : const int32_t secToMin = 60;
292 2038 : *offset = (int32_t)(localTime.tm_gmtoff / secToMin);
293 2038 : return TRACE_SUCCESS;
294 : }
|