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 1650 : void *TraceDlopen(const char *libPath, int32_t mode)
19 : {
20 1650 : return mmDlopen(libPath, mode);
21 : }
22 :
23 3300 : void *TraceDlsym(void *handle, const char *funcName)
24 : {
25 3300 : return mmDlsym(handle, funcName);
26 : }
27 :
28 1600 : int32_t TraceDlclose(void *handle)
29 : {
30 1600 : return mmDlclose(handle);
31 : }
32 :
33 4331 : int32_t TraceGetPid(void)
34 : {
35 4331 : return mmGetPid();
36 : }
37 :
38 59 : int32_t TraceRaise(int32_t signo)
39 : {
40 : #if defined _ADIAG_LLT_
41 59 : return 0;
42 : #else
43 : return raise(signo);
44 : #endif
45 : }
46 :
47 4736 : int32_t TraceChmod(const char *dirPath, uint32_t mode)
48 : {
49 4736 : return chmod(dirPath, mode);
50 : }
51 :
52 4726 : int32_t TraceChown(const char *dirPath, uint32_t uid, uint32_t gid)
53 : {
54 4726 : return chown(dirPath, uid, gid);
55 : }
56 :
57 15844 : TraStatus TraceMkdir(const char *dirPath, uint32_t mode, uint32_t uid, uint32_t gid)
58 : {
59 15844 : ADIAG_CHK_NULL_PTR(dirPath, return TRACE_FAILURE);
60 :
61 15844 : if (access(dirPath, F_OK) != 0) {
62 4826 : if ((mkdir(dirPath, mode) != 0) && access(dirPath, F_OK) != 0) {
63 100 : return TRACE_FAILURE;
64 : }
65 4726 : if (TraceChmod(dirPath, mode) != 0) {
66 0 : return TRACE_FAILURE;
67 : }
68 4726 : if (TraceChown(dirPath, uid, gid) != 0) {
69 0 : return TRACE_FAILURE;
70 : }
71 : }
72 :
73 15744 : return TRACE_SUCCESS;
74 : }
75 :
76 1860 : int32_t TraceRmdir(const char *pathName)
77 : {
78 1860 : return mmRmdir(pathName);
79 : }
80 :
81 3799 : int32_t TraceOpen(const char *filePath, int32_t flag, uint32_t mode)
82 : {
83 3799 : int32_t fd = open(filePath, flag, mode);
84 3799 : if (fd >= 0) {
85 3799 : (void)fchmod(fd, mode);
86 : }
87 3799 : return fd;
88 : }
89 :
90 1938 : void TraceClose(int32_t *fd)
91 : {
92 1938 : if ((fd == NULL) || (*fd < 0)) {
93 169 : return;
94 : }
95 :
96 1769 : (void)close(*fd);
97 1769 : *fd = -1;
98 : }
99 :
100 : /**
101 : * @brief get string of env
102 : * @param[in] env: environment value obtained from the environment variable
103 : * @param[out] buf: buffer to save string
104 : * @param[in] len: buffer length
105 : * @return TraStatus
106 : */
107 2776 : TraStatus TraceHandleEnvString(const char *env, char *buf, uint32_t len)
108 : {
109 2776 : ADIAG_CHK_NULL_PTR(buf, return TRACE_FAILURE);
110 2776 : if ((env == NULL) || (strlen(env) == 0U) || (strlen(env) > (size_t)len)) {
111 2356 : ADIAG_WAR("Environment variable is null or the length exceeds %u.", len);
112 2356 : return TRACE_FAILURE;
113 : }
114 :
115 420 : int32_t ret = strcpy_s(buf, (size_t)len, env);
116 420 : ADIAG_CHK_EXPR_ACTION(ret != EOK, return TRACE_FAILURE, "strcpy env string failed, ret=%d, strerr=%s.",
117 : ret, strerror(AdiagGetErrorCode()));
118 420 : return TRACE_SUCCESS;
119 : }
120 :
121 9981 : int32_t TraceRealPath(const char *path, char *realPath, int32_t realPathLen)
122 : {
123 9981 : return mmRealPath(path, realPath, realPathLen);
124 : }
125 :
126 620 : int32_t TraceAccess(const char *path, int32_t mode)
127 : {
128 620 : return mmAccess2(path, mode);
129 : }
130 :
131 254 : int32_t TraceCreateTaskWithThreadAttr(TraceThread *threadHandle, const TraceUserBlock *funcBlock,
132 : const TraceThreadAttr *threadAttr)
133 : {
134 254 : return mmCreateTaskWithThreadAttr(threadHandle, funcBlock, threadAttr);
135 : }
136 :
137 241 : int32_t TraceJoinTask(TraceThread *threadHandle)
138 : {
139 241 : return mmJoinTask(threadHandle);
140 : }
141 :
142 247 : int32_t TraceSetThreadName(const char *threadName)
143 : {
144 247 : return mmSetCurrentThreadName(threadName);
145 : }
146 :
147 3506 : int32_t TraceGetTimeOfDay(TraceTimeVal *timeVal, TraceTimeZone *timeZone)
148 : {
149 3506 : return mmGetTimeOfDay(timeVal, timeZone);
150 : }
151 :
152 1570 : int32_t TraceLocalTimeR(const time_t *timep, struct tm *result)
153 : {
154 1570 : return mmLocalTimeR(timep, result);
155 : }
156 :
157 26 : int32_t TraceSocket(int32_t sockFamily, int32_t type, int32_t protocol)
158 : {
159 26 : return mmSocket(sockFamily, type, protocol);
160 : }
161 :
162 11 : int32_t TraceBind(int32_t sockFd, TraceSockAddr *addr, size_t addrLen)
163 : {
164 11 : return mmBind((mmSockHandle)sockFd, (mmSockAddr *)addr, (mmSocklen_t)addrLen);
165 : }
166 :
167 23 : int32_t TraceCloseSocket(int32_t sockFd)
168 : {
169 23 : return mmCloseSocket((mmSockHandle)sockFd);
170 : }
171 :
172 10 : int32_t TraceConnect(int32_t sockFd, struct sockaddr *addr, size_t addrLen)
173 : {
174 10 : return mmConnect((mmSockHandle)sockFd, (mmSockAddr *)addr, (mmSocklen_t)addrLen);
175 : }
176 :
177 21365368 : STATIC INLINE int32_t IsLeapYear(int32_t year)
178 : {
179 : // years can be divisible by 4, but not by 100, or years can be divisible by 400
180 21365368 : return ((((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0)) ? 1 : 0;
181 : }
182 :
183 : /**
184 : * @brief get local time string from timestamp, must be reentrant, cannot print msg
185 : * @param [out] timeInfo: local time struct
186 : * @param [in] sec: seconds from 1970/1/1
187 : * @param [in] timeZone: current time zone
188 : * @param [in] dst: daylight time
189 : * @return void
190 : */
191 368828 : STATIC void CalLocalTime(struct tm *timeInfo, time_t sec, time_t timeZone, int32_t dst)
192 : {
193 368828 : const time_t oneMin = 60; // 1m: 60s
194 368828 : const time_t oneHour = 3600; // 1h: 3600s
195 368828 : const time_t oneDay = 86400; // 24h: 86400s
196 368828 : const time_t oneYear = 365; // 365 days
197 :
198 368828 : time_t realSec = sec - timeZone; // Adjust for timezone
199 368828 : realSec += oneHour * dst; // Adjust for daylight time
200 368828 : time_t days = realSec / oneDay; // Days passed since epoch
201 368828 : time_t seconds = realSec % oneDay; // Remaining seconds
202 :
203 368828 : timeInfo->tm_isdst = dst;
204 368828 : timeInfo->tm_hour = (int32_t)(seconds / oneHour);
205 368828 : timeInfo->tm_min = (int32_t)((seconds % oneHour) / oneMin);
206 368828 : timeInfo->tm_sec = (int32_t)((seconds % oneHour) % oneMin);
207 :
208 : // 1/1/1970 was a Thursday, that is, day 4 from the POV of the tm structure * where sunday = 0,
209 : // so to calculate the day of the week we have to add 4 * and take the modulo by 7.
210 368828 : timeInfo->tm_wday = (int32_t)((days + 4) % 7); // start from Thursday
211 : // Calculate the current year
212 368828 : timeInfo->tm_year = 1970; // start from 1970
213 20627712 : while (1) {
214 : // Leap years have one day more
215 20996540 : time_t yearDays = oneYear + (time_t)IsLeapYear(timeInfo->tm_year);
216 20996540 : if (yearDays > days) {
217 368828 : break;
218 : }
219 20627712 : days -= yearDays;
220 20627712 : timeInfo->tm_year++;
221 : }
222 368828 : timeInfo->tm_yday = (int32_t)days; // Number of day of the current year
223 :
224 : // We need to calculate in which month and day of the month we are. To do *,
225 : // so we need to skip days according to how many days there are in each * month,
226 : // and adjust for the leap year that has one more day in February.
227 368828 : int32_t mDays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // days of month: 31, 30, 28/29
228 368828 : mDays[1] += IsLeapYear(timeInfo->tm_year); // leap year
229 :
230 368828 : timeInfo->tm_mon = 0;
231 2578940 : while (days >= mDays[timeInfo->tm_mon]) {
232 2210112 : days -= mDays[timeInfo->tm_mon];
233 2210112 : timeInfo->tm_mon++;
234 : }
235 :
236 368828 : timeInfo->tm_mon++; // Add 1 since our 'month' is zero-based
237 368828 : timeInfo->tm_mday = (int32_t)days + 1; // Add 1 since our 'days' is zero-based
238 368828 : }
239 :
240 : /**
241 : * @brief init daylight saving time
242 : * @return TraStatus
243 : */
244 1610 : TraStatus TraceTimeDstInit(void)
245 : {
246 1610 : TraceTimeVal timeVal = { 0, 0 };
247 : struct tm tmInfo;
248 1610 : (void)memset_s(&tmInfo, sizeof(tmInfo), 0, sizeof(tmInfo));
249 : // sync time zone
250 1610 : tzset();
251 1610 : if (TraceGetTimeOfDay(&timeVal, NULL) != TRACE_SUCCESS) {
252 40 : ADIAG_ERR("get time of day failed, errno=%s.", strerror(AdiagGetErrorCode()));
253 40 : return TRACE_FAILURE;
254 : }
255 1570 : const time_t sec = timeVal.tv_sec;
256 1570 : if (TraceLocalTimeR(&sec, &tmInfo) != TRACE_SUCCESS) {
257 20 : ADIAG_ERR("get local time failed, errno=%s.", strerror(AdiagGetErrorCode()));
258 20 : return TRACE_FAILURE;
259 : }
260 :
261 1550 : g_timeDst = tmInfo.tm_isdst;
262 1550 : return TRACE_SUCCESS;
263 : }
264 :
265 : /**
266 : * @brief get local time string from timestamp, must be reentrant, cannot print msg
267 : * @param [in] timestamp: timestamp
268 : * @param [out] buffer: buffer to save timestamp str
269 : * @param [in] bufSize: size of buffer
270 : * @return TraStatus
271 : */
272 363749 : TraStatus TimestampToStr(uint64_t timestamp, char *buffer, uint32_t bufSize)
273 : {
274 363749 : uint64_t tmpTime = (timestamp / SEC_TO_NS) & (uint64_t)LONG_MAX;
275 363749 : time_t secTime = (time_t)tmpTime;
276 363749 : uint64_t microTime = timestamp % SEC_TO_NS;
277 : struct tm now;
278 363749 : CalLocalTime(&now, secTime, (time_t)timezone, g_timeDst);
279 :
280 363749 : int32_t err = sprintf_s(buffer, bufSize, "%04ld-%02d-%02d %02d:%02d:%02d.%03llu.%03llu ",
281 : now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec,
282 : (microTime / TIME_ONE_THOUSAND_MS) / TIME_ONE_THOUSAND_MS,
283 363749 : (microTime / TIME_ONE_THOUSAND_MS) % TIME_ONE_THOUSAND_MS);
284 363749 : if (err == -1) {
285 20 : return TRACE_RING_BUFFER_SPRINTF_FAILED;
286 : }
287 363729 : return TRACE_SUCCESS;
288 : }
289 :
290 : /**
291 : * @brief get local time string from timestamp, must be reentrant, cannot print msg
292 : * @param [in] timestamp: timestamp
293 : * @param [out] buffer: buffer to save timestamp str
294 : * @param [in] bufSize: size of buffer
295 : * @return TraStatus
296 : */
297 5079 : TraStatus TimestampToFileStr(uint64_t timestamp, char *buffer, uint32_t bufSize)
298 : {
299 5079 : uint64_t tmpTime = (timestamp / SEC_TO_NS) & (uint64_t)LONG_MAX;
300 5079 : time_t secTime = (time_t)tmpTime;
301 5079 : uint64_t microTime = timestamp % SEC_TO_NS;
302 : struct tm now;
303 5079 : CalLocalTime(&now, secTime, (time_t)timezone, g_timeDst);
304 :
305 5079 : int32_t err = sprintf_s(buffer, bufSize, "%04ld%02d%02d%02d%02d%02d%03llu%03llu",
306 : now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec,
307 : (microTime / TIME_ONE_THOUSAND_MS) / TIME_ONE_THOUSAND_MS,
308 5079 : (microTime / TIME_ONE_THOUSAND_MS) % TIME_ONE_THOUSAND_MS);
309 5079 : if (err == -1) {
310 21 : return TRACE_RING_BUFFER_SPRINTF_FAILED;
311 : }
312 5058 : return TRACE_SUCCESS;
313 : }
314 :
315 : /**
316 : * @brief get the offset between local time and UTC
317 : * @param [out] offset: offset, unit:minute
318 : * @return TraStatus
319 : */
320 1896 : TraStatus TraceGetTimeOffset(int32_t *offset)
321 : {
322 1896 : TraceTimeVal tv = { 0 };
323 1896 : struct tm localTime = { 0 };
324 :
325 1896 : if (TraceGetTimeOfDay(&tv, NULL) != TRACE_SUCCESS) {
326 20 : return TRACE_FAILURE;
327 : }
328 1876 : time_t utcTime = tv.tv_sec;
329 1876 : if (localtime_r(&utcTime, &localTime) == NULL) {
330 20 : return TRACE_FAILURE;
331 : }
332 1856 : const int32_t secToMin = 60;
333 1856 : *offset = (int32_t)(localTime.tm_gmtoff / secToMin);
334 1856 : return TRACE_SUCCESS;
335 : }
|