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