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_recorder.h"
12 : #include "adiag_print.h"
13 : #include "trace_system_api.h"
14 : #include "trace_attr.h"
15 : #include "trace_types.h"
16 : #include <stdarg.h>
17 :
18 : #define TRACE_FILE_ASCEND_PATH "ascend"
19 : #define TRACE_FILE_SUB_PATH "atrace"
20 : #define TRACE_DIR_HEAD "trace"
21 : #define TRACE_DIR_MODE 0750U
22 : #define TRACE_FILE_MODE 0640U
23 : #define FILE_SEPARATOR "/"
24 :
25 : #define TRACE_DIR_NUM_DEFAULT 10
26 : #define TRACE_DIR_NUM_MIN 10
27 : #define TRACE_DIR_NUM_MAX 1000
28 :
29 : STATIC TraceRecorderMgr* g_recorderMgr = NULL;
30 :
31 : #ifndef ATRACE_ROOT_PATH
32 1024 : STATIC TraStatus TraceGetHomeDir(char* const homedir, uint32_t len)
33 : {
34 1024 : ADIAG_CHK_NULL_PTR(homedir, return TRACE_FAILURE);
35 :
36 : int32_t ret;
37 1024 : const struct passwd* userInfo = getpwuid(getuid());
38 1024 : if (userInfo != NULL) {
39 1024 : ret = strcpy_s(homedir, len, userInfo->pw_dir);
40 : } else {
41 0 : ret = strcpy_s(homedir, len, "");
42 : }
43 1024 : ADIAG_CHK_EXPR_ACTION(
44 : ret != EOK, return TRACE_FAILURE, "strcpy_s home directory failed, result=%d, strerr=%s.", ret,
45 : strerror(AdiagGetErrorCode()));
46 :
47 1024 : ADIAG_INF("home_directory=%s.", homedir);
48 1024 : return TRACE_SUCCESS;
49 : }
50 :
51 242 : STATIC TraStatus TraceMkdirRecur(const char* dirPath)
52 : {
53 242 : TraStatus err = TRACE_SUCCESS;
54 242 : char* newDir = strdup(dirPath);
55 242 : if (newDir == NULL) {
56 22 : ADIAG_ERR("strdup failed, strerr=%s.", strerror(AdiagGetErrorCode()));
57 22 : return TRACE_FAILURE;
58 : }
59 220 : char* path = (char*)AdiagMalloc(MAX_FILEDIR_LEN + 1U);
60 220 : ADIAG_CHK_EXPR_ACTION(
61 : path == NULL, return TRACE_FAILURE, "malloc path failed, strerr=%s", strerror(AdiagGetErrorCode()));
62 :
63 220 : char* tmpNewDir = newDir;
64 220 : char* tmpPath = path;
65 220 : char* token = strsep(&newDir, FILE_SEPARATOR);
66 4510 : while (token != NULL) {
67 4378 : if (strcmp(token, "") == 0) {
68 264 : token = strsep(&newDir, FILE_SEPARATOR);
69 264 : continue;
70 : }
71 4114 : char nextDir[MAX_FILEDIR_LEN + 1U] = {0};
72 4114 : int32_t ret = snprintf_s(nextDir, MAX_FILEDIR_LEN + 1U, MAX_FILEDIR_LEN, "/%s", token);
73 4114 : if (ret == -1) {
74 22 : ADIAG_ERR("copy data failed, strerr=%s.", strerror(AdiagGetErrorCode()));
75 22 : err = TRACE_FAILURE;
76 88 : break;
77 : }
78 4092 : ret = strncat_s(path, MAX_FILEDIR_LEN + 1U, nextDir, strlen(nextDir));
79 4092 : if (ret != 0) {
80 22 : ADIAG_ERR("strncat_s failed, strerr=%s.", strerror(AdiagGetErrorCode()));
81 22 : err = TRACE_FAILURE;
82 22 : break;
83 : }
84 4070 : err = TraceMkdir((const char*)path, TRACE_DIR_MODE, TraceAttrGetUid(), TraceAttrGetGid());
85 4070 : if (err != TRACE_SUCCESS) {
86 44 : ADIAG_ERR("mkdir failed, ret=%d, strerr=%s.", err, strerror(AdiagGetErrorCode()));
87 44 : break;
88 : }
89 4026 : token = strsep(&newDir, FILE_SEPARATOR);
90 : }
91 220 : ADIAG_SAFE_FREE(tmpPath);
92 220 : ADIAG_SAFE_FREE(tmpNewDir);
93 220 : return err;
94 : }
95 :
96 1718 : STATIC TraStatus TraceNormalizeEnvPath(char* envDir, uint32_t len)
97 : {
98 1718 : if ((envDir == NULL) || (len == 0U) || (envDir[0] == '\0')) {
99 22 : ADIAG_WAR("ASCEND_WORK_PATH is invalid.");
100 22 : return TRACE_FAILURE;
101 : }
102 1696 : if (envDir[0] == '/') {
103 1542 : return TRACE_SUCCESS;
104 : }
105 :
106 154 : char cwd[MAX_FILEDIR_LEN + 1U] = {0};
107 154 : if (getcwd(cwd, sizeof(cwd)) == NULL) {
108 22 : ADIAG_WAR("get current directory failed, strerr=%s.", strerror(AdiagGetErrorCode()));
109 22 : return TRACE_FAILURE;
110 : }
111 :
112 132 : char absPath[MAX_FILEDIR_LEN + 1U] = {0};
113 132 : int32_t ret = snprintf_s(absPath, sizeof(absPath), sizeof(absPath) - 1U, "%s/%s", cwd, envDir);
114 132 : if (ret == -1) {
115 22 : ADIAG_WAR(
116 : "build ASCEND_WORK_PATH absolute path failed, path may exceed %u bytes, cwd=%s, env=%s.", MAX_FILEDIR_LEN,
117 : cwd, envDir);
118 22 : return TRACE_FAILURE;
119 : }
120 110 : ret = strcpy_s(envDir, len, absPath);
121 110 : if (ret != EOK) {
122 22 : ADIAG_WAR("copy ASCEND_WORK_PATH absolute path failed, ret=%d.", ret);
123 22 : return TRACE_FAILURE;
124 : }
125 88 : return TRACE_SUCCESS;
126 : }
127 :
128 1718 : STATIC TraStatus TraceGetValidPath(char* envDir, uint32_t len)
129 : {
130 1718 : if (TraceNormalizeEnvPath(envDir, len) != TRACE_SUCCESS) {
131 88 : return TRACE_FAILURE;
132 : }
133 1630 : if ((TraceAccess(envDir, F_OK) != EN_OK) && (TraceMkdirRecur(envDir) != EN_OK)) {
134 110 : ADIAG_WAR("path %s doesn't exist.", envDir);
135 110 : return TRACE_FAILURE;
136 : }
137 1520 : if (TraceAccess(envDir, W_OK) != EN_OK) {
138 22 : ADIAG_WAR("path %s doesn't have write permission.", envDir);
139 22 : return TRACE_FAILURE;
140 : }
141 :
142 1498 : char* realPath = (char*)AdiagMalloc(TRACE_MAX_PATH);
143 1498 : ADIAG_CHK_EXPR_ACTION(
144 : realPath == NULL, return TRACE_FAILURE, "malloc real path failed, strerr=%s", strerror(AdiagGetErrorCode()));
145 :
146 1498 : if ((TraceRealPath(envDir, realPath, TRACE_MAX_PATH) != EN_OK) && (AdiagGetErrorCode() != ENOENT)) {
147 22 : ADIAG_WAR("can not get realpath, path=%s, strerr=%s.", envDir, strerror(AdiagGetErrorCode()));
148 22 : ADIAG_SAFE_FREE(realPath);
149 22 : return TRACE_FAILURE;
150 : }
151 1476 : int32_t res = snprintf_truncated_s(envDir, len, "%s", realPath);
152 1476 : if (res < 0) {
153 0 : ADIAG_ERR("get path failed, ret=%d.", res);
154 0 : ADIAG_SAFE_FREE(realPath);
155 0 : return TRACE_FAILURE;
156 : }
157 1476 : ADIAG_SAFE_FREE(realPath);
158 1476 : return TRACE_SUCCESS;
159 : }
160 :
161 2500 : STATIC TraStatus TraceGetEnvPath(char* envDir, uint32_t len)
162 : {
163 2500 : const char* env = NULL;
164 2500 : MM_SYS_GET_ENV(MM_ENV_ASCEND_WORK_PATH, (env));
165 2500 : TraStatus ret = TraceHandleEnvString(env, envDir, len);
166 2500 : if (ret != TRACE_SUCCESS) {
167 782 : return TRACE_FAILURE;
168 : }
169 1718 : ADIAG_RUN_INF("get path by env ASCEND_WORK_PATH: %s", envDir);
170 :
171 1718 : ret = TraceGetValidPath(envDir, len);
172 1718 : if (ret != TRACE_SUCCESS) {
173 242 : ADIAG_RUN_INF("can not use ASCEND_WORK_PATH, please check the warning logs.");
174 242 : return TRACE_FAILURE;
175 : }
176 1476 : return TRACE_SUCCESS;
177 : }
178 : #endif
179 :
180 : /**
181 : * @brief get dir num by env
182 : * @param [in] mgr: recorder manager
183 : * @return void
184 : */
185 2500 : STATIC void TraceInitDirNum(TraceRecorderMgr* mgr)
186 : {
187 2500 : mgr->maxDirNum = TRACE_DIR_NUM_DEFAULT;
188 2500 : const char* env = NULL;
189 2500 : MM_SYS_GET_ENV(MM_ENV_ASCEND_TRACE_RECORD_NUM, (env));
190 2500 : if (env == NULL) {
191 2390 : ADIAG_INF("doesn't set env ASCEND_TRACE_RECORD_NUM, use default dir num=%d.", mgr->maxDirNum);
192 2390 : return;
193 : }
194 :
195 110 : ADIAG_RUN_INF("get dir num by env ASCEND_TRACE_RECORD_NUM: %s", env);
196 110 : int32_t value = -1;
197 110 : if ((AdiagStrToInt(env, &value) == TRACE_SUCCESS) && (value <= TRACE_DIR_NUM_MAX) && (value >= TRACE_DIR_NUM_MIN)) {
198 110 : ADIAG_INF("set dir num=%d by env ASCEND_TRACE_RECORD_NUM.", value);
199 110 : mgr->maxDirNum = value;
200 : } else {
201 0 : ADIAG_WAR(
202 : "invalid value [%s] for ASCEND_TRACE_RECORD_NUM, expected range: [10, 1000]. Use default dir num=%d.", env,
203 : mgr->maxDirNum);
204 : }
205 : }
206 :
207 : /**
208 : * @brief get root path
209 : * @param [in] mgr: recorder manager
210 : * @return TraStatus
211 : */
212 2500 : STATIC TraStatus TraceInitRootPath(TraceRecorderMgr* mgr)
213 : {
214 2500 : ADIAG_CHK_NULL_PTR(mgr, return TRACE_FAILURE);
215 : int32_t res;
216 :
217 : #ifdef ATRACE_ROOT_PATH
218 : res = snprintf_truncated_s(mgr->rootPath, MAX_FILEDIR_LEN + 1U, "%s", ATRACE_ROOT_PATH);
219 : if (res < 0) {
220 : ADIAG_ERR("snprintf_truncated_s failed, ret=%d.", res);
221 : return TRACE_FAILURE;
222 : }
223 : #else
224 2500 : char* path = (char*)AdiagMalloc(MAX_FILEDIR_LEN + 1U);
225 2500 : ADIAG_CHK_EXPR_ACTION(
226 : path == NULL, return TRACE_FAILURE, "malloc root path failed, strerr=%s", strerror(AdiagGetErrorCode()));
227 :
228 2500 : TraStatus ret = TraceGetEnvPath(path, MAX_FILEDIR_LEN + 1U);
229 2500 : if (ret == TRACE_SUCCESS) {
230 1476 : res = snprintf_truncated_s(mgr->rootPath, MAX_FILEDIR_LEN + 1U, "%s", path);
231 : } else {
232 : // get process user home path
233 1024 : ret = TraceGetHomeDir(path, MAX_FILEDIR_LEN + 1U);
234 1024 : if (ret != TRACE_SUCCESS) {
235 0 : ADIAG_SAFE_FREE(path);
236 0 : ADIAG_ERR("get home directory failed, ret=%d.", ret);
237 0 : return TRACE_FAILURE;
238 : }
239 1024 : res = snprintf_truncated_s(mgr->rootPath, MAX_FILEDIR_LEN + 1U, "%s/%s", path, TRACE_FILE_ASCEND_PATH);
240 : }
241 :
242 2500 : if (res < 0) {
243 0 : ADIAG_SAFE_FREE(path);
244 0 : ADIAG_ERR("snprintf_truncated_s failed, ret=%d.", res);
245 0 : return TRACE_FAILURE;
246 : }
247 2500 : ADIAG_SAFE_FREE(path);
248 : #endif
249 2500 : ADIAG_INF("use root path: %s", mgr->rootPath);
250 2500 : return TRACE_SUCCESS;
251 : }
252 :
253 4988 : STATIC void TraceRecorderClearList(TraceDirList* list)
254 : {
255 4988 : TraceDirNode* curNode = list->head;
256 4988 : TraceDirNode* next = NULL;
257 6331 : while (curNode != NULL) {
258 1343 : next = curNode->next;
259 1343 : ADIAG_SAFE_FREE(curNode);
260 1343 : curNode = next;
261 : }
262 4988 : list->count = 0;
263 4988 : }
264 :
265 2500 : TraStatus TraceRecorderInit(void)
266 : {
267 2500 : g_recorderMgr = (TraceRecorderMgr*)AdiagMalloc(sizeof(TraceRecorderMgr));
268 2500 : ADIAG_CHK_EXPR_ACTION(g_recorderMgr == NULL, return TRACE_FAILURE, "init recorder mgr failed.");
269 :
270 2500 : TraStatus ret = TraceInitRootPath(g_recorderMgr);
271 2500 : if (ret != TRACE_SUCCESS) {
272 0 : ADIAG_SAFE_FREE(g_recorderMgr);
273 0 : ADIAG_ERR("init file root path failed, ret=%d.", ret);
274 0 : return TRACE_FAILURE;
275 : }
276 :
277 2500 : TraceInitDirNum(g_recorderMgr);
278 :
279 2500 : return TRACE_SUCCESS;
280 : }
281 :
282 2578 : void TraceRecorderExit(void)
283 : {
284 2578 : if (g_recorderMgr == NULL) {
285 84 : ADIAG_WAR("file list is null.");
286 84 : return;
287 : }
288 :
289 2494 : TraceRecorderClearList(&g_recorderMgr->hostDirList);
290 2494 : TraceRecorderClearList(&g_recorderMgr->deviceDirList);
291 2494 : if (g_recorderMgr->exitDir != NULL) {
292 45 : ADIAG_SAFE_FREE(g_recorderMgr->exitDir);
293 : }
294 2494 : ADIAG_SAFE_FREE(g_recorderMgr);
295 : }
296 :
297 2046 : STATIC TraceDirNode* TraceRecorderListPopHead(TraceDirList* dirList)
298 : {
299 2046 : (void)AdiagLockGet(&dirList->lock);
300 2046 : TraceDirNode* dirNode = dirList->head;
301 2046 : dirList->head = dirNode->next;
302 2046 : if (dirList->head != NULL) {
303 2046 : dirList->head->prev = NULL;
304 : } else {
305 0 : dirList->tail = NULL;
306 : }
307 2046 : dirNode->next = NULL;
308 2046 : dirNode->prev = NULL;
309 2046 : dirList->count--;
310 2046 : (void)AdiagLockRelease(&dirList->lock);
311 2046 : return dirNode;
312 : }
313 :
314 3390 : STATIC void TraceRecorderListAppend(TraceDirList* dirList, TraceDirNode* newNode)
315 : {
316 3390 : (void)AdiagLockGet(&dirList->lock);
317 3390 : newNode->prev = dirList->tail;
318 3390 : newNode->next = NULL;
319 3390 : if (dirList->tail != NULL) {
320 3014 : dirList->tail->next = newNode;
321 : } else {
322 376 : dirList->head = newNode;
323 : }
324 3390 : dirList->tail = newNode;
325 3390 : dirList->count++;
326 3390 : (void)AdiagLockRelease(&dirList->lock);
327 3390 : }
328 :
329 3654 : STATIC TraceDirNode* TraceRecorderListFind(TraceDirList* dirList, const char* dirPath)
330 : {
331 3654 : (void)AdiagLockGet(&dirList->lock);
332 3654 : TraceDirNode* curNode = dirList->head;
333 28712 : while (curNode != NULL) {
334 25322 : if (strcmp(curNode->dirPath, dirPath) == 0) {
335 264 : (void)AdiagLockRelease(&dirList->lock);
336 264 : return curNode;
337 : }
338 25058 : curNode = curNode->next;
339 : }
340 3390 : (void)AdiagLockRelease(&dirList->lock);
341 3390 : return NULL;
342 : }
343 :
344 3458 : STATIC void TraceRecorderSaveNode(const TraceDirInfo* dirInfo, TraceDirNode* dirNew)
345 : {
346 : // if exit_event, no need to aging
347 3458 : if (strncmp(dirInfo->eventName, TRACER_EVENT_EXIT, strlen(TRACER_EVENT_EXIT)) == 0) {
348 68 : if (g_recorderMgr->exitDir != NULL) {
349 23 : ADIAG_SAFE_FREE(g_recorderMgr->exitDir);
350 : }
351 68 : g_recorderMgr->exitDir = dirNew;
352 68 : return;
353 : }
354 :
355 3390 : TraceDirList* dirList = (dirInfo->isDevice) ? &g_recorderMgr->deviceDirList : &g_recorderMgr->hostDirList;
356 : // delete node and age the dir
357 3390 : if (dirList->count >= g_recorderMgr->maxDirNum) {
358 2046 : TraceDirNode* deleteNode = TraceRecorderListPopHead(dirList);
359 2046 : TraStatus ret = TraceRmdir(deleteNode->dirPath);
360 2046 : if (ret != 0) {
361 0 : ADIAG_WAR(
362 : "can not remove dir %s, ret=%d, strerr=%s.", deleteNode->dirPath, ret, strerror(AdiagGetErrorCode()));
363 : } else {
364 2046 : ADIAG_INF("remove dir %s successfully.", deleteNode->dirPath);
365 : }
366 2046 : ADIAG_SAFE_FREE(deleteNode);
367 : }
368 : // append new node
369 3390 : TraceRecorderListAppend(dirList, dirNew);
370 : }
371 :
372 11496 : STATIC TraStatus TraceRecorderCreateDirWithCheck(const char* path, int32_t* errCode)
373 : {
374 11496 : TraStatus ret = TraceMkdir(path, TRACE_DIR_MODE, TraceAttrGetUid(), TraceAttrGetGid());
375 11496 : if (ret != TRACE_SUCCESS) {
376 132 : int32_t code = AdiagGetErrorCode();
377 132 : if (errCode != NULL) {
378 132 : *errCode = code;
379 : }
380 132 : ADIAG_ERR("mkdir %s failed, ret=%d, strerr=%s.", path, ret, strerror(code));
381 132 : return TRACE_FAILURE;
382 : }
383 11364 : return ret;
384 : }
385 :
386 66 : STATIC void TraceRecorderLogBuildFailure(
387 : const char* label, const char* stage, const TraceDirInfo* dirInfo, int32_t errCode)
388 : {
389 66 : ADIAG_ERR(
390 : "create trace %s failed, stage=%s, reason=snprintf_s, rootPath=%s, "
391 : "eventName=%s, pid=%d, dirTime=%s, limit=%zu, strerr=%s.",
392 : label, stage, g_recorderMgr->rootPath, dirInfo->eventName, dirInfo->pid, dirInfo->dirTime,
393 : (size_t)MAX_FILEPATH_LEN, strerror(errCode));
394 66 : }
395 :
396 132 : STATIC void TraceRecorderLogMkdirFailure(const char* label, const char* stage, const char* dirPath, int32_t errCode)
397 : {
398 132 : ADIAG_ERR(
399 : "create trace %s failed, stage=%s, reason=mkdir, "
400 : "rootPath=%s, dirPath=%s, dirPathLen=%zu, limit=%zu, strerr=%s.",
401 : label, stage, g_recorderMgr->rootPath, dirPath, strlen(dirPath), (size_t)MAX_FILEPATH_LEN, strerror(errCode));
402 132 : }
403 :
404 3964 : STATIC TraStatus TraceRecorderCreateRootDir(void)
405 : {
406 3964 : TraStatus ret = TraceMkdir(g_recorderMgr->rootPath, TRACE_DIR_MODE, TraceAttrGetUid(), TraceAttrGetGid());
407 3964 : if (ret != TRACE_SUCCESS) {
408 44 : int32_t errCode = AdiagGetErrorCode();
409 44 : ADIAG_ERR(
410 : "create trace root directory failed, ret=%d, stage=root_dir, reason=mkdir, "
411 : "rootPath=%s, rootPathLen=%zu, limit=%zu, strerr=%s.",
412 : ret, g_recorderMgr->rootPath, strlen(g_recorderMgr->rootPath), (size_t)MAX_FILEPATH_LEN, strerror(errCode));
413 44 : return TRACE_FAILURE;
414 : }
415 3920 : return TRACE_SUCCESS;
416 : }
417 :
418 11562 : STATIC TraStatus TraceRecorderCreateFormattedDir(
419 : TraceDirNode* dirNew, const char* label, const char* stage, const TraceDirInfo* dirInfo, const char* format, ...)
420 : {
421 : va_list args;
422 11562 : va_start(args, format);
423 11562 : int32_t ret = vsnprintf_s(dirNew->dirPath, MAX_FILEPATH_LEN + 1U, MAX_FILEPATH_LEN, format, args);
424 11562 : va_end(args);
425 11562 : if (ret == -1) {
426 66 : int32_t errCode = AdiagGetErrorCode();
427 66 : TraceRecorderLogBuildFailure(label, stage, dirInfo, errCode);
428 66 : return TRACE_FAILURE;
429 : }
430 11496 : int32_t errCode = 0;
431 11496 : if (TraceRecorderCreateDirWithCheck(dirNew->dirPath, &errCode) != TRACE_SUCCESS) {
432 132 : TraceRecorderLogMkdirFailure(label, stage, dirNew->dirPath, errCode);
433 132 : return TRACE_FAILURE;
434 : }
435 11364 : return TRACE_SUCCESS;
436 : }
437 :
438 3722 : STATIC TraceDirNode* TraceRecorderFindExistingDir(const TraceDirInfo* dirInfo, TraceDirNode* dirNew)
439 : {
440 3722 : if (strncmp(dirInfo->eventName, TRACER_EVENT_EXIT, strlen(TRACER_EVENT_EXIT)) == 0) {
441 68 : return NULL;
442 : }
443 3654 : TraceDirList* dirList = (dirInfo->isDevice) ? &g_recorderMgr->deviceDirList : &g_recorderMgr->hostDirList;
444 3654 : return TraceRecorderListFind(dirList, dirNew->dirPath);
445 : }
446 :
447 3964 : const TraceDirNode* TraceRecorderGetDirPath(const TraceDirInfo* dirInfo)
448 : {
449 : // ~/ascend
450 3964 : if (TraceRecorderCreateRootDir() != TRACE_SUCCESS) {
451 44 : return NULL;
452 : }
453 :
454 3920 : TraceDirNode* dirNew = (TraceDirNode*)AdiagMalloc(sizeof(TraceDirNode));
455 3920 : ADIAG_CHK_EXPR_ACTION(dirNew == NULL, return NULL, "create dir failed.");
456 :
457 : // ~/ascend/atrace
458 3920 : if (TraceRecorderCreateFormattedDir(
459 3920 : dirNew, "atrace directory", "atrace_dir", dirInfo, "%s/%s", g_recorderMgr->rootPath, TRACE_FILE_SUB_PATH) !=
460 : TRACE_SUCCESS) {
461 66 : goto failed;
462 : }
463 :
464 : // ~/ascend/atrace/trace_{attr_group_id}_{attr_pid}_{attr_time}
465 7708 : if (TraceRecorderCreateFormattedDir(
466 3854 : dirNew, "first directory", "first_trace_dir", dirInfo, "%s/%s/%s_%d_%d_%s", g_recorderMgr->rootPath,
467 : TRACE_FILE_SUB_PATH, TRACE_DIR_HEAD, TraceAttrGetPgid(), TraceAttrGetPid(),
468 : TraceAttrGetTime()) != TRACE_SUCCESS) {
469 66 : goto failed;
470 : }
471 :
472 : // ~/ascend/atrace/trace_{attr_group_id}_{attr_pid}_{attr_time}/{tracer_name}_event_{pid}_time
473 7576 : if (TraceRecorderCreateFormattedDir(
474 : dirNew, "second directory", "second_event_dir", dirInfo, "%s/%s/%s_%d_%d_%s/%s_event_%d_%s",
475 3788 : g_recorderMgr->rootPath, TRACE_FILE_SUB_PATH, TRACE_DIR_HEAD, TraceAttrGetPgid(), TraceAttrGetPid(),
476 3788 : TraceAttrGetTime(), dirInfo->eventName, dirInfo->pid, dirInfo->dirTime) != TRACE_SUCCESS) {
477 66 : goto failed;
478 : }
479 :
480 3722 : TraceDirNode* existNode = TraceRecorderFindExistingDir(dirInfo, dirNew);
481 3722 : if (existNode != NULL) {
482 264 : ADIAG_SAFE_FREE(dirNew);
483 264 : return existNode;
484 : }
485 :
486 3458 : TraceRecorderSaveNode(dirInfo, dirNew);
487 3458 : return dirNew;
488 :
489 198 : failed:
490 198 : ADIAG_SAFE_FREE(dirNew);
491 198 : return NULL;
492 : }
493 :
494 3744 : TraStatus TraceRecorderGetFd(const TraceDirInfo* dirInfo, const TraceFileInfo* fileInfo, int32_t* fd)
495 : {
496 3744 : ADIAG_CHK_NULL_PTR(fileInfo, return TRACE_FAILURE);
497 3744 : ADIAG_CHK_NULL_PTR(dirInfo, return TRACE_FAILURE);
498 3744 : (void)AdiagLockGet(&g_recorderMgr->lock);
499 3744 : const TraceDirNode* dir = TraceRecorderGetDirPath(dirInfo);
500 3744 : if (dir == NULL) {
501 22 : ADIAG_ERR("get dir failed.");
502 22 : (void)AdiagLockRelease(&g_recorderMgr->lock);
503 22 : return TRACE_FAILURE;
504 : }
505 :
506 3722 : char filePath[MAX_FULLPATH_LEN + 1U] = {0};
507 3722 : int32_t ret = snprintf_s(
508 3722 : filePath, MAX_FULLPATH_LEN + 1U, MAX_FULLPATH_LEN, "%s/%s_tracer_%s%s", dir->dirPath, fileInfo->tracerName,
509 3722 : fileInfo->objName, fileInfo->suffix);
510 3722 : if (ret == -1) {
511 0 : int32_t errCode = AdiagGetErrorCode();
512 0 : (void)AdiagLockRelease(&g_recorderMgr->lock);
513 0 : ADIAG_ERR("snprintf_s file path failed, ret=%d, strerr=%s.", ret, strerror(errCode));
514 0 : return TRACE_FAILURE;
515 : }
516 3722 : int32_t fileFd = TraceOpen(filePath, (uint32_t)O_CREAT | (uint32_t)O_WRONLY | (uint32_t)O_APPEND, TRACE_FILE_MODE);
517 3722 : int32_t errCode = (fileFd < 0) ? AdiagGetErrorCode() : 0;
518 3722 : (void)AdiagLockRelease(&g_recorderMgr->lock);
519 3722 : ADIAG_CHK_EXPR_ACTION(
520 : fileFd < 0, return TRACE_FAILURE, "open file failed, file=%s, strerr=%s.", filePath, strerror(errCode));
521 :
522 3698 : *fd = fileFd;
523 3698 : return TRACE_SUCCESS;
524 : }
525 :
526 73727 : TraStatus TraceRecorderWrite(int32_t fd, const char* msg, uint32_t len)
527 : {
528 73727 : int32_t ret = (int32_t)write(fd, msg, len);
529 73727 : if ((ret < 0) || ((uint32_t)ret != len)) {
530 1 : return TRACE_FAILURE;
531 : }
532 73726 : return TRACE_SUCCESS;
533 : }
534 :
535 669 : STATIC TraStatus TraceRecorderSafeMkdirPathWithBuffer(const TraceDirInfo* dirInfo, char* path, size_t len)
536 : {
537 669 : if ((path == NULL) || (len == 0)) {
538 0 : return TRACE_INVALID_PARAM;
539 : }
540 669 : int32_t ret = TraceMkdir(g_recorderMgr->rootPath, TRACE_DIR_MODE, TraceAttrGetUid(), TraceAttrGetGid());
541 669 : if (ret != TRACE_SUCCESS) {
542 44 : return TRACE_FAILURE;
543 : }
544 :
545 625 : ret = snprintf_s(path, len, len - 1U, "%s/%s", g_recorderMgr->rootPath, TRACE_FILE_SUB_PATH);
546 625 : if (ret == -1) {
547 22 : return TRACE_FAILURE;
548 : }
549 603 : ret = TraceMkdir(path, TRACE_DIR_MODE, TraceAttrGetUid(), TraceAttrGetGid());
550 603 : if (ret != TRACE_SUCCESS) {
551 44 : return TRACE_FAILURE;
552 : }
553 :
554 559 : ret = snprintf_s(
555 559 : path, len, len - 1U, "%s/%s/%s_%d_%d_%s", g_recorderMgr->rootPath, TRACE_FILE_SUB_PATH, TRACE_DIR_HEAD,
556 : TraceAttrGetPgid(), TraceAttrGetPid(), TraceAttrGetTime());
557 559 : if (ret == -1) {
558 22 : return TRACE_FAILURE;
559 : }
560 537 : ret = TraceMkdir(path, TRACE_DIR_MODE, TraceAttrGetUid(), TraceAttrGetGid());
561 537 : if (ret != TRACE_SUCCESS) {
562 22 : return TRACE_FAILURE;
563 : }
564 :
565 515 : ret = TraceRecorderSafeGetDirPath(dirInfo, path, len);
566 515 : if (ret != TRACE_SUCCESS) {
567 22 : return TRACE_FAILURE;
568 : }
569 493 : ret = TraceMkdir(path, TRACE_DIR_MODE, TraceAttrGetUid(), TraceAttrGetGid());
570 493 : if (ret != TRACE_SUCCESS) {
571 22 : return ret;
572 : }
573 471 : return TRACE_SUCCESS;
574 : }
575 :
576 277 : TraStatus TraceRecorderSafeMkdirPath(const TraceDirInfo* dirInfo)
577 : {
578 277 : char path[MAX_FULLPATH_LEN + 1U] = {0};
579 277 : return TraceRecorderSafeMkdirPathWithBuffer(dirInfo, path, MAX_FULLPATH_LEN + 1U);
580 : }
581 :
582 823 : TraStatus TraceRecorderSafeGetDirPath(const TraceDirInfo* dirInfo, char* path, size_t len)
583 : {
584 823 : if ((dirInfo == NULL) || (path == NULL) || (len == 0)) {
585 66 : return TRACE_INVALID_PARAM;
586 : }
587 757 : int32_t ret = snprintf_s(
588 757 : path, len, len - 1U, "%s/%s/%s_%d_%d_%s/%s_event_%d_%s", g_recorderMgr->rootPath, TRACE_FILE_SUB_PATH,
589 757 : TRACE_DIR_HEAD, TraceAttrGetPgid(), TraceAttrGetPid(), TraceAttrGetTime(), dirInfo->eventName, dirInfo->pid,
590 757 : dirInfo->dirTime);
591 757 : if (ret == -1) {
592 44 : return TRACE_FAILURE;
593 : }
594 713 : return TRACE_SUCCESS;
595 : }
596 :
597 : /**
598 : * @brief get file fd to write
599 : use for signal_callback_func, only call reentrant function
600 : * @param [in] dirInfo: dir info, for dir name
601 : * @param [in] fileInfo: file info, for file name
602 : * @param [out] fd: file handle
603 : * @return TraStatus
604 : */
605 414 : TraStatus TraceRecorderSafeGetFd(const TraceDirInfo* dirInfo, const TraceFileInfo* fileInfo, int32_t* fd)
606 : {
607 414 : if ((dirInfo == NULL) || (fileInfo == NULL) || (fd == NULL)) {
608 22 : return TRACE_INVALID_PARAM;
609 : }
610 :
611 392 : char path[MAX_FULLPATH_LEN + 1U] = {0};
612 392 : TraStatus ret = TraceRecorderSafeMkdirPathWithBuffer(dirInfo, path, MAX_FULLPATH_LEN + 1U);
613 392 : if (ret != TRACE_SUCCESS) {
614 44 : return ret;
615 : }
616 :
617 348 : size_t pathLen = strlen(path);
618 348 : if (pathLen >= MAX_FULLPATH_LEN) {
619 0 : return TRACE_FAILURE;
620 : }
621 348 : ret = snprintf_s(
622 : path + pathLen, MAX_FULLPATH_LEN + 1U - pathLen, MAX_FULLPATH_LEN - pathLen, "/%s_tracer_%s%s",
623 348 : fileInfo->tracerName, fileInfo->objName, fileInfo->suffix);
624 348 : if (ret == -1) {
625 22 : return TRACE_FAILURE;
626 : }
627 :
628 326 : errno_t err = strncpy_s(g_recorderMgr->corePath, MAX_FULLPATH_LEN + 1U, path, strlen(path));
629 326 : if (err != EOK) {
630 0 : return TRACE_FAILURE;
631 : }
632 :
633 326 : int32_t fileFd = TraceOpen(path, (uint32_t)O_CREAT | (uint32_t)O_WRONLY | (uint32_t)O_APPEND, TRACE_FILE_MODE);
634 326 : if (fileFd < 0) {
635 22 : return TRACE_FAILURE;
636 : }
637 :
638 304 : *fd = fileFd;
639 304 : return TRACE_SUCCESS;
640 : }
641 :
642 0 : const char* TraceRecorderSafeGetFilePath(void) { return g_recorderMgr->corePath; }
|