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 "adx_api.h"
12 : #include "mmpa_api.h"
13 : #include "ascend_hal.h"
14 : #include "protocol/adx_msg_proto.h"
15 : #include "log/adx_log.h"
16 : #include "common/file_utils.h"
17 : #include "device/adx_dsmi.h"
18 : #include "config.h"
19 : #include "create_func.h"
20 : #include "adcore_api.h"
21 : #include "memory_utils.h"
22 : #include "adx_msg.h"
23 : #include "adx_comm_opt_manager.h"
24 : using namespace Adx;
25 : static constexpr int32_t BLOCK_RETURN_CODE = 4;
26 : static constexpr int32_t RESULT_LEN_MAX = 100;
27 : static constexpr uint32_t DEFAULT_TIMEOUT = 10000; // 10000ms
28 :
29 : /**
30 : * @brief hdc connect core dump server
31 : * @param [out] client : send file communication client handle
32 : * @param [in] devId : send file device id
33 : * @return CommHandle : client handle
34 : */
35 26 : static CommHandle AdxHdcConnect(CommHandle &client, uint16_t devId,
36 : AdxHdcServiceType hdcType = HDC_SERVICE_TYPE_IDE_FILE_TRANS)
37 : {
38 26 : std::map<std::string, std::string> info;
39 26 : info[OPT_DEVICE_KEY] = std::to_string(devId);
40 26 : info[OPT_SERVICE_KEY] = std::to_string(hdcType);
41 26 : CommHandle session = {OptType::COMM_HDC, ADX_OPT_INVALID_HANDLE, NR_COMPONENTS, -1, nullptr};
42 26 : std::unique_ptr<AdxCommOpt> opt (CreateAdxCommOpt(OptType::COMM_HDC));
43 26 : IDE_CTRL_VALUE_FAILED(opt != nullptr, return session,
44 : "create hdc commopt exception");
45 26 : bool ret = AdxCommOptManager::Instance().CommOptsRegister(opt);
46 26 : IDE_CTRL_VALUE_FAILED(ret, return client, "register hdc failed");
47 26 : client = AdxCommOptManager::Instance().OpenClient(OptType::COMM_HDC, info);
48 26 : IDE_CTRL_VALUE_FAILED(client.session != ADX_OPT_INVALID_HANDLE, return client,
49 : "open client failed");
50 26 : session = AdxCommOptManager::Instance().Connect(client, info);
51 26 : if (session.session == ADX_OPT_INVALID_HANDLE) {
52 0 : (void)AdxCommOptManager::Instance().CloseClient(client);
53 : }
54 26 : return session;
55 26 : }
56 :
57 : /**
58 : * @brief send file common opreate
59 : * @param [in] handle : send file communication handle
60 : * @param [in] srcFile : send file source file with path
61 : * @return IDE_DAEMON_OK(0) : send file success, IDE_DAEMON_ERROR(-1) : send file failed
62 : */
63 8 : static int32_t AdxCommonGetFile(const CommHandle &handle, const std::string &srcFile)
64 : {
65 8 : IDE_CTRL_VALUE_FAILED(!srcFile.empty(), return IDE_DAEMON_ERROR, "source file input invalid");
66 8 : IDE_CTRL_VALUE_FAILED(FileUtils::CheckNonCrossPath(srcFile), return IDE_DAEMON_ERROR,
67 : "Cross-path access may exist on the path: %s", srcFile.c_str());
68 : // create dir if not exist
69 2 : std::string saveDirName = FileUtils::GetFileDir(srcFile);
70 2 : if (!FileUtils::IsFileExist(saveDirName)) {
71 1 : if (FileUtils::CreateDir(saveDirName) != IDE_DAEMON_NONE_ERROR) {
72 1 : IDE_LOGE("create dir failed path: %s", saveDirName.c_str());
73 1 : return IDE_DAEMON_ERROR;
74 : }
75 : }
76 : // get file
77 1 : int32_t fd = mmOpen2(srcFile.c_str(), M_RDWR | M_CREAT | M_BINARY | M_TRUNC, M_IRUSR | M_IWRITE);
78 1 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
79 1 : IDE_CTRL_VALUE_FAILED(fd >= 0, return IDE_DAEMON_ERROR, "open file exception, info : %s",
80 : mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN));
81 :
82 1 : int32_t err = AdxMsgProto::RecvFile(handle, fd);
83 1 : if (err != IDE_DAEMON_NONE_ERROR && err != IDE_DAEMON_CHANNEL_ERROR) {
84 0 : mmClose(fd);
85 0 : fd = -1;
86 0 : IDE_LOGE("receive file failed, info : %s", srcFile.c_str());
87 0 : (void)remove(srcFile.c_str());
88 0 : return IDE_DAEMON_ERROR;
89 : }
90 :
91 1 : mmClose(fd);
92 1 : fd = -1;
93 :
94 1 : if (err == IDE_DAEMON_CHANNEL_ERROR) {
95 1 : IDE_LOGE("send file receive response failed, " \
96 : "maybe multiple msnpureports executed at the same time, which is not supported, " \
97 : "please execute msnpureport only once per time later if needed");
98 : }
99 1 : return IDE_DAEMON_OK;
100 2 : }
101 :
102 : /**
103 : * @brief get device file
104 : * @param [in] devId : physical device id
105 : * @param [in] desPath : send file to destination path
106 : * @param [in] logType : file type, stackcore, slog, bbox, message
107 : * @param [in] timeout : 0 wait_always, > 0 wait_timeout; unit: ms
108 : * @return IDE_DAEMON_OK(0) : get file success, IDE_DAEMON_ERROR(-1) : get file failed
109 : */
110 14 : int32_t AdxGetDeviceFileTimeout(uint16_t devId, IdeString desPath, IdeString logType, uint32_t timeout)
111 : {
112 14 : int32_t err = IDE_DAEMON_ERROR;
113 14 : IDE_CTRL_VALUE_FAILED(desPath != nullptr && logType != nullptr, return err,
114 : "send file input parameter invalid");
115 14 : IDE_RUN_LOGI("get device file to %s", desPath);
116 14 : CommHandle client = {OptType::COMM_HDC, ADX_OPT_INVALID_HANDLE, NR_COMPONENTS, -1, nullptr};
117 14 : uint32_t logId = 0;
118 14 : err = AdxGetLogIdByPhyId(devId, &logId);
119 14 : IDE_CTRL_VALUE_FAILED(err == IDE_DAEMON_OK, return err, "get device logic id failed");
120 14 : CommHandle handle = AdxHdcConnect(client, logId);
121 14 : IDE_CTRL_VALUE_FAILED(handle.session != ADX_OPT_INVALID_HANDLE, return IDE_DAEMON_ERROR,
122 : "send file hdc client connect failed");
123 14 : handle.timeout = timeout;
124 14 : std::string basePath = desPath;
125 14 : std::string value;
126 14 : int32_t result = IDE_DAEMON_OK;
127 28 : MsgCode code = AdxMsgProto::SendMsgData(handle, IDE_FILE_GETD_REQ, MsgStatus::MSG_STATUS_NONE_ERROR,
128 14 : logType, strlen(logType) + 1);
129 14 : IDE_CTRL_VALUE_FAILED(code == IDE_DAEMON_NONE_ERROR, goto GET_ERROR, "send file hand shake failed");
130 : do {
131 : // recv file name
132 15 : code = AdxMsgProto::GetStringMsgData(handle, value);
133 15 : IDE_CTRL_VALUE_FAILED(code == IDE_DAEMON_NONE_ERROR, goto GET_ERROR, "get file shake response failed, ret=%d",
134 : static_cast<int32_t>(code));
135 10 : size_t msgSize = IdeDaemon::Common::Config::CONTAINER_NO_SUPPORT_MESSAGE.length();
136 10 : if (value.compare(0, msgSize, IdeDaemon::Common::Config::CONTAINER_NO_SUPPORT_MESSAGE) == 0) {
137 1 : result = BLOCK_RETURN_CODE;
138 1 : break;
139 : }
140 9 : msgSize = IdeDaemon::Common::Config::SEND_END_MSG.length();
141 9 : if (value.compare(0, msgSize, IdeDaemon::Common::Config::SEND_END_MSG) == 0) {
142 1 : break;
143 : }
144 8 : IDE_LOGD("receive file relative path and name is %s", value.c_str());
145 8 : value = basePath + OS_SPLIT_STR + value;
146 : #if (OS_TYPE != LINUX)
147 : value = FileUtils::ReplaceAll(value, "/", "\\");
148 : #endif
149 8 : err = AdxCommonGetFile(handle, value);
150 8 : if (err != IDE_DAEMON_OK) {
151 7 : IDE_LOGE("get file process failed");
152 7 : break;
153 : }
154 1 : IDE_LOGI("receive file file data successfully");
155 1 : (void)mmChmod(value.c_str(), M_IRUSR); // readonly, 400
156 1 : } while (true);
157 :
158 14 : GET_ERROR:
159 14 : (void)AdxCommOptManager::Instance().Close(handle);
160 14 : (void)AdxCommOptManager::Instance().CloseClient(client);
161 14 : return result;
162 14 : }
163 :
164 : /**
165 : * @brief get file value from the peer end and write to file
166 : * @param [in] handle : handle for communicating with the peer end
167 : * @param [in] fd : file descriptor
168 : * @return IDE_DAEMON_OK(0) : recv file success, IDE_DAEMON_ERROR(-1) : recv file failed
169 : */
170 13 : static int32_t AdxRecvFile(const CommHandle &handle, int32_t fd)
171 : {
172 13 : IDE_CTRL_VALUE_FAILED(fd >= 0, return IDE_DAEMON_ERROR, "file fd input failed");
173 13 : MsgProto *msg = nullptr;
174 13 : int32_t length = 0;
175 : while (true) {
176 14 : int32_t ret = AdxCommOptManager::Instance().Read(handle, reinterpret_cast<IdeRecvBuffT>(&msg),
177 : length, DEFAULT_TIMEOUT);
178 14 : IDE_CTRL_VALUE_FAILED((ret == IDE_DAEMON_OK) && (msg != nullptr), return IDE_DAEMON_ERROR,
179 : "receive file failed, ret: %d", ret);
180 13 : if (msg->msgType == MsgType::MSG_CTRL) { // check the message is ctrl or not
181 1 : IDE_LOGW("receive control message from device, stop receiving");
182 1 : IDE_XFREE_AND_SET_NULL(msg);
183 1 : return IDE_DAEMON_ERROR;
184 : }
185 12 : if (msg->sliceLen != 0) {
186 12 : mmSsize_t len = mmWrite(fd, msg->data, msg->sliceLen);
187 12 : if (len < 0) {
188 1 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
189 1 : IDE_LOGE("write file failed, error info: [%s]",
190 : mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN));
191 1 : IDE_XFREE_AND_SET_NULL(msg);
192 1 : return IDE_DAEMON_ERROR;
193 : }
194 : }
195 :
196 11 : if (msg->totalLen == msg->sliceLen + msg->offset) {
197 10 : break;
198 : }
199 :
200 1 : IDE_XFREE_AND_SET_NULL(msg);
201 1 : }
202 10 : if (AdxSendMsg(&handle, HDC_END_MSG, strlen(HDC_END_MSG)) != IDE_DAEMON_OK) {
203 2 : IDE_LOGW("send file response message exception");
204 : }
205 :
206 10 : IDE_XFREE_AND_SET_NULL(msg);
207 10 : return IDE_DAEMON_OK;
208 : }
209 :
210 : /**
211 : * @brief get device file
212 : * @param [in] devId : physical device id
213 : * @param [in] desPath : send file to destination path
214 : * @param [in] logType : file type, stackcore, slog, bbox, message
215 : * @return IDE_DAEMON_OK(0) : get file success, IDE_DAEMON_ERROR(-1) : get file failed
216 : */
217 14 : int32_t AdxGetDeviceFile(uint16_t devId, IdeString desPath, IdeString logType)
218 : {
219 14 : return AdxGetDeviceFileTimeout(devId, desPath, logType, DEFAULT_TIMEOUT);
220 : }
221 :
222 : /**
223 : * @brief create file and receive value
224 : * @param [in] handle : handle for communicating with the peer end
225 : * @param [in] file : the file name
226 : * @return IDE_DAEMON_OK(0) : recv file success, IDE_DAEMON_ERROR(-1) : recv file failed
227 : */
228 17 : static int32_t AdxCreateFileAndRecvValue(const CommHandle &handle, std::string &file)
229 : {
230 17 : IDE_CTRL_VALUE_FAILED(FileUtils::CheckNonCrossPath(file), return IDE_DAEMON_ERROR,
231 : "Cross-path access may exist on the path: %s", file.c_str());
232 : // create dir if not exist
233 16 : std::string saveDirName = FileUtils::GetFileDir(file);
234 16 : if (!FileUtils::IsFileExist(saveDirName)) {
235 14 : if (FileUtils::CreateDir(saveDirName) != IDE_DAEMON_NONE_ERROR) {
236 1 : IDE_LOGE("create dir failed path: %s", saveDirName.c_str());
237 1 : return IDE_DAEMON_ERROR;
238 : }
239 : }
240 : // get file
241 15 : int32_t fd = mmOpen2(file.c_str(), M_RDWR | M_CREAT | M_BINARY | M_TRUNC, M_IRUSR | M_IWRITE);
242 15 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
243 15 : IDE_CTRL_VALUE_FAILED(fd >= 0, return IDE_DAEMON_ERROR, "open file exception, info : %s",
244 : mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN));
245 :
246 13 : int32_t err = AdxRecvFile(handle, fd);
247 13 : if (err == IDE_DAEMON_ERROR) {
248 3 : mmClose(fd);
249 3 : fd = -1;
250 3 : IDE_LOGE("receive file failed, info : %s", file.c_str());
251 3 : (void)remove(file.c_str());
252 3 : return IDE_DAEMON_ERROR;
253 : }
254 10 : mmClose(fd);
255 10 : fd = -1;
256 10 : (void)mmChmod(file.c_str(), M_IRUSR); // readonly, 400
257 10 : return IDE_DAEMON_OK;
258 16 : }
259 :
260 : /**
261 : * @brief get device file from specified hdc server and component
262 : * @param [in] devId : physical device id
263 : * @param [in] desPath : send file to destination path
264 : * @param [in] logType : file type
265 : * @param [in] hdcType : hdc server type
266 : * @param [in] compType : component type
267 : * @return IDE_DAEMON_OK(0) : get file success, IDE_DAEMON_ERROR(-1) : get file failed
268 : */
269 14 : int32_t AdxGetSpecifiedFile(uint16_t devId, IdeString desPath, IdeString logType, int32_t hdcType, int32_t compType)
270 : {
271 14 : int32_t err = IDE_DAEMON_ERROR;
272 14 : IDE_CTRL_VALUE_FAILED((desPath != nullptr) && (logType != nullptr), return err,
273 : "send file input parameter invalid");
274 13 : IDE_RUN_LOGI("get device file to %s", desPath);
275 13 : CommHandle client = {OptType::COMM_HDC, ADX_OPT_INVALID_HANDLE, NR_COMPONENTS, -1, nullptr};
276 13 : uint32_t logId = 0;
277 13 : err = AdxGetLogIdByPhyId(devId, &logId);
278 13 : IDE_CTRL_VALUE_FAILED(err == IDE_DAEMON_OK, return err, "get device logic id failed");
279 12 : CommHandle handle = AdxHdcConnect(client, logId, static_cast<AdxHdcServiceType>(hdcType));
280 12 : IDE_CTRL_VALUE_FAILED(handle.session != ADX_OPT_INVALID_HANDLE, return IDE_DAEMON_ERROR,
281 : "send file hdc client connect failed");
282 12 : handle.comp = static_cast<ComponentType>(compType);
283 12 : err = AdxSendMsg(static_cast<AdxCommConHandle>(&handle), logType, strlen(logType));
284 12 : IDE_CTRL_VALUE_FAILED(err == IDE_DAEMON_OK, return err, "send data message failed");
285 22 : std::string basePath = desPath;
286 : do {
287 20 : uint32_t len = RESULT_LEN_MAX;
288 20 : IdeStringBuffer ptr = static_cast<IdeStringBuffer>(IdeXmalloc(len));
289 20 : err = AdxRecvMsg(&handle, &ptr, &len, DEFAULT_TIMEOUT);
290 20 : if (err != IDE_DAEMON_OK) {
291 1 : IDE_XFREE_AND_SET_NULL(ptr);
292 1 : IDE_LOGE("receive message failed, ret: %d", err);
293 1 : break;
294 : }
295 19 : std::string value(ptr);
296 19 : IDE_XFREE_AND_SET_NULL(ptr);
297 19 : size_t msgSize = IdeDaemon::Common::Config::CONTAINER_NO_SUPPORT_MESSAGE.length();
298 19 : if (value.compare(0, msgSize, IdeDaemon::Common::Config::CONTAINER_NO_SUPPORT_MESSAGE) == 0) {
299 1 : err = BLOCK_RETURN_CODE;
300 1 : break;
301 : }
302 18 : msgSize = sizeof(HDC_END_MSG);
303 18 : if (value.compare(0, msgSize, HDC_END_MSG) == 0) {
304 4 : break;
305 : }
306 14 : err = AdxSendMsg(&handle, HDC_END_MSG, strlen(HDC_END_MSG));
307 14 : if (err != IDE_DAEMON_OK) {
308 1 : IDE_LOGW("send name response message exception");
309 : }
310 14 : IDE_LOGD("receive file relative path and name is %s", value.c_str());
311 14 : value = basePath + OS_SPLIT_STR + value;
312 :
313 14 : if (AdxCreateFileAndRecvValue(handle, value) != IDE_DAEMON_OK) {
314 5 : err = IDE_DAEMON_ERROR;
315 5 : break;
316 : }
317 28 : } while (true);
318 :
319 11 : (void)AdxCommOptManager::Instance().Close(handle);
320 11 : (void)AdxCommOptManager::Instance().CloseClient(client);
321 11 : return err;
322 11 : }
323 :
324 5 : int32_t AdxRecvDevFileTimeout(AdxCommHandle handle, AdxString desPath, uint32_t timeout, AdxStringBuffer fileName,
325 : uint32_t fileNameLen)
326 : {
327 5 : IDE_CTRL_VALUE_FAILED(handle != nullptr, return IDE_DAEMON_ERROR, "handle is NULL.");
328 5 : IDE_CTRL_VALUE_FAILED(desPath != nullptr, return IDE_DAEMON_ERROR, "desPath is NULL.");
329 5 : IDE_CTRL_VALUE_FAILED(fileName != nullptr, return IDE_DAEMON_ERROR, "fileName is NULL.");
330 :
331 5 : uint32_t len = fileNameLen;
332 5 : int32_t ret = AdxRecvMsg(handle, &fileName, &len, timeout);
333 5 : if (ret != IDE_DAEMON_OK) {
334 1 : return ret;
335 : }
336 4 : std::string value(fileName);
337 4 : if (value.compare(HDC_END_MSG) == 0) {
338 1 : return IDE_DAEMON_ERROR;
339 : }
340 3 : value = std::string(desPath) + OS_SPLIT_STR + value;
341 3 : if (AdxCreateFileAndRecvValue(*handle, value) != IDE_DAEMON_OK) {
342 2 : return IDE_DAEMON_ERROR;
343 : }
344 1 : return IDE_DAEMON_OK;
345 4 : }
|