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(
36 : CommHandle& client, uint16_t devId, 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, "create hdc commopt exception");
44 26 : bool ret = AdxCommOptManager::Instance().CommOptsRegister(opt);
45 26 : IDE_CTRL_VALUE_FAILED(ret, return client, "register hdc failed");
46 26 : client = AdxCommOptManager::Instance().OpenClient(OptType::COMM_HDC, info);
47 26 : IDE_CTRL_VALUE_FAILED(client.session != ADX_OPT_INVALID_HANDLE, return client, "open client failed");
48 26 : session = AdxCommOptManager::Instance().Connect(client, info);
49 26 : if (session.session == ADX_OPT_INVALID_HANDLE) {
50 0 : (void)AdxCommOptManager::Instance().CloseClient(client);
51 : }
52 26 : return session;
53 26 : }
54 :
55 : /**
56 : * @brief send file common opreate
57 : * @param [in] handle : send file communication handle
58 : * @param [in] srcFile : send file source file with path
59 : * @return IDE_DAEMON_OK(0) : send file success, IDE_DAEMON_ERROR(-1) : send file failed
60 : */
61 8 : static int32_t AdxCommonGetFile(const CommHandle& handle, const std::string& srcFile)
62 : {
63 8 : IDE_CTRL_VALUE_FAILED(!srcFile.empty(), return IDE_DAEMON_ERROR, "source file input invalid");
64 8 : IDE_CTRL_VALUE_FAILED(
65 : FileUtils::CheckNonCrossPath(srcFile), return IDE_DAEMON_ERROR, "Cross-path access may exist on the path: %s",
66 : srcFile.c_str());
67 : // create dir if not exist
68 2 : std::string saveDirName = FileUtils::GetFileDir(srcFile);
69 2 : if (!FileUtils::IsFileExist(saveDirName)) {
70 1 : if (FileUtils::CreateDir(saveDirName) != IDE_DAEMON_NONE_ERROR) {
71 1 : IDE_LOGE("create dir failed path: %s", saveDirName.c_str());
72 1 : return IDE_DAEMON_ERROR;
73 : }
74 : }
75 : // get file
76 1 : int32_t fd = mmOpen2(srcFile.c_str(), M_RDWR | M_CREAT | M_BINARY | M_TRUNC, M_IRUSR | M_IWRITE);
77 1 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
78 1 : IDE_CTRL_VALUE_FAILED(
79 : 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, "send file input parameter invalid");
114 14 : IDE_RUN_LOGI("get device file to %s", desPath);
115 14 : CommHandle client = {OptType::COMM_HDC, ADX_OPT_INVALID_HANDLE, NR_COMPONENTS, -1, nullptr};
116 14 : uint32_t logId = 0;
117 14 : err = AdxGetLogIdByPhyId(devId, &logId);
118 14 : IDE_CTRL_VALUE_FAILED(err == IDE_DAEMON_OK, return err, "get device logic id failed");
119 14 : CommHandle handle = AdxHdcConnect(client, logId);
120 14 : IDE_CTRL_VALUE_FAILED(
121 : handle.session != ADX_OPT_INVALID_HANDLE, return IDE_DAEMON_ERROR, "send file hdc client connect failed");
122 14 : handle.timeout = timeout;
123 14 : std::string basePath = desPath;
124 14 : std::string value;
125 14 : int32_t result = IDE_DAEMON_OK;
126 28 : MsgCode code = AdxMsgProto::SendMsgData(
127 14 : handle, IDE_FILE_GETD_REQ, MsgStatus::MSG_STATUS_NONE_ERROR, logType, strlen(logType) + 1);
128 14 : IDE_CTRL_VALUE_FAILED(code == IDE_DAEMON_NONE_ERROR, goto GET_ERROR, "send file hand shake failed");
129 : do {
130 : // recv file name
131 15 : code = AdxMsgProto::GetStringMsgData(handle, value);
132 15 : IDE_CTRL_VALUE_FAILED(
133 : 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 : int32_t ret =
177 14 : AdxCommOptManager::Instance().Read(handle, reinterpret_cast<IdeRecvBuffT>(&msg), length, DEFAULT_TIMEOUT);
178 14 : IDE_CTRL_VALUE_FAILED(
179 : (ret == IDE_DAEMON_OK) && (msg != nullptr), return IDE_DAEMON_ERROR, "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(
190 : "write file failed, error info: [%s]",
191 : mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN));
192 1 : IDE_XFREE_AND_SET_NULL(msg);
193 1 : return IDE_DAEMON_ERROR;
194 : }
195 : }
196 :
197 11 : if (msg->totalLen == msg->sliceLen + msg->offset) {
198 10 : break;
199 : }
200 :
201 1 : IDE_XFREE_AND_SET_NULL(msg);
202 1 : }
203 10 : if (AdxSendMsg(&handle, HDC_END_MSG, strlen(HDC_END_MSG)) != IDE_DAEMON_OK) {
204 2 : IDE_LOGW("send file response message exception");
205 : }
206 :
207 10 : IDE_XFREE_AND_SET_NULL(msg);
208 10 : return IDE_DAEMON_OK;
209 : }
210 :
211 : /**
212 : * @brief get device file
213 : * @param [in] devId : physical device id
214 : * @param [in] desPath : send file to destination path
215 : * @param [in] logType : file type, stackcore, slog, bbox, message
216 : * @return IDE_DAEMON_OK(0) : get file success, IDE_DAEMON_ERROR(-1) : get file failed
217 : */
218 14 : int32_t AdxGetDeviceFile(uint16_t devId, IdeString desPath, IdeString logType)
219 : {
220 14 : return AdxGetDeviceFileTimeout(devId, desPath, logType, DEFAULT_TIMEOUT);
221 : }
222 :
223 : /**
224 : * @brief create file and receive value
225 : * @param [in] handle : handle for communicating with the peer end
226 : * @param [in] file : the file name
227 : * @return IDE_DAEMON_OK(0) : recv file success, IDE_DAEMON_ERROR(-1) : recv file failed
228 : */
229 17 : static int32_t AdxCreateFileAndRecvValue(const CommHandle& handle, std::string& file)
230 : {
231 17 : IDE_CTRL_VALUE_FAILED(
232 : FileUtils::CheckNonCrossPath(file), return IDE_DAEMON_ERROR, "Cross-path access may exist on the path: %s",
233 : file.c_str());
234 : // create dir if not exist
235 16 : std::string saveDirName = FileUtils::GetFileDir(file);
236 16 : if (!FileUtils::IsFileExist(saveDirName)) {
237 14 : if (FileUtils::CreateDir(saveDirName) != IDE_DAEMON_NONE_ERROR) {
238 1 : IDE_LOGE("create dir failed path: %s", saveDirName.c_str());
239 1 : return IDE_DAEMON_ERROR;
240 : }
241 : }
242 : // get file
243 15 : int32_t fd = mmOpen2(file.c_str(), M_RDWR | M_CREAT | M_BINARY | M_TRUNC, M_IRUSR | M_IWRITE);
244 15 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
245 15 : IDE_CTRL_VALUE_FAILED(
246 : fd >= 0, return IDE_DAEMON_ERROR, "open file exception, info : %s",
247 : mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN));
248 :
249 13 : int32_t err = AdxRecvFile(handle, fd);
250 13 : if (err == IDE_DAEMON_ERROR) {
251 3 : mmClose(fd);
252 3 : fd = -1;
253 3 : IDE_LOGE("receive file failed, info : %s", file.c_str());
254 3 : (void)remove(file.c_str());
255 3 : return IDE_DAEMON_ERROR;
256 : }
257 10 : mmClose(fd);
258 10 : fd = -1;
259 10 : (void)mmChmod(file.c_str(), M_IRUSR); // readonly, 400
260 10 : return IDE_DAEMON_OK;
261 16 : }
262 :
263 : /**
264 : * @brief get device file from specified hdc server and component
265 : * @param [in] devId : physical device id
266 : * @param [in] desPath : send file to destination path
267 : * @param [in] logType : file type
268 : * @param [in] hdcType : hdc server type
269 : * @param [in] compType : component type
270 : * @return IDE_DAEMON_OK(0) : get file success, IDE_DAEMON_ERROR(-1) : get file failed
271 : */
272 14 : int32_t AdxGetSpecifiedFile(uint16_t devId, IdeString desPath, IdeString logType, int32_t hdcType, int32_t compType)
273 : {
274 14 : int32_t err = IDE_DAEMON_ERROR;
275 14 : IDE_CTRL_VALUE_FAILED(
276 : (desPath != nullptr) && (logType != nullptr), return err, "send file input parameter invalid");
277 13 : IDE_RUN_LOGI("get device file to %s", desPath);
278 13 : CommHandle client = {OptType::COMM_HDC, ADX_OPT_INVALID_HANDLE, NR_COMPONENTS, -1, nullptr};
279 13 : uint32_t logId = 0;
280 13 : err = AdxGetLogIdByPhyId(devId, &logId);
281 13 : IDE_CTRL_VALUE_FAILED(err == IDE_DAEMON_OK, return err, "get device logic id failed");
282 12 : CommHandle handle = AdxHdcConnect(client, logId, static_cast<AdxHdcServiceType>(hdcType));
283 12 : IDE_CTRL_VALUE_FAILED(
284 : handle.session != ADX_OPT_INVALID_HANDLE, return IDE_DAEMON_ERROR, "send file hdc client connect failed");
285 12 : handle.comp = static_cast<ComponentType>(compType);
286 12 : err = AdxSendMsg(static_cast<AdxCommConHandle>(&handle), logType, strlen(logType));
287 12 : IDE_CTRL_VALUE_FAILED(err == IDE_DAEMON_OK, return err, "send data message failed");
288 22 : std::string basePath = desPath;
289 : do {
290 20 : uint32_t len = RESULT_LEN_MAX;
291 20 : IdeStringBuffer ptr = static_cast<IdeStringBuffer>(IdeXmalloc(len));
292 20 : err = AdxRecvMsg(&handle, &ptr, &len, DEFAULT_TIMEOUT);
293 20 : if (err != IDE_DAEMON_OK) {
294 1 : IDE_XFREE_AND_SET_NULL(ptr);
295 1 : IDE_LOGE("receive message failed, ret: %d", err);
296 1 : break;
297 : }
298 19 : std::string value(ptr);
299 19 : IDE_XFREE_AND_SET_NULL(ptr);
300 19 : size_t msgSize = IdeDaemon::Common::Config::CONTAINER_NO_SUPPORT_MESSAGE.length();
301 19 : if (value.compare(0, msgSize, IdeDaemon::Common::Config::CONTAINER_NO_SUPPORT_MESSAGE) == 0) {
302 1 : err = BLOCK_RETURN_CODE;
303 1 : break;
304 : }
305 18 : msgSize = sizeof(HDC_END_MSG);
306 18 : if (value.compare(0, msgSize, HDC_END_MSG) == 0) {
307 4 : break;
308 : }
309 14 : err = AdxSendMsg(&handle, HDC_END_MSG, strlen(HDC_END_MSG));
310 14 : if (err != IDE_DAEMON_OK) {
311 1 : IDE_LOGW("send name response message exception");
312 : }
313 14 : IDE_LOGD("receive file relative path and name is %s", value.c_str());
314 14 : value = basePath + OS_SPLIT_STR + value;
315 :
316 14 : if (AdxCreateFileAndRecvValue(handle, value) != IDE_DAEMON_OK) {
317 5 : err = IDE_DAEMON_ERROR;
318 5 : break;
319 : }
320 28 : } while (true);
321 :
322 11 : (void)AdxCommOptManager::Instance().Close(handle);
323 11 : (void)AdxCommOptManager::Instance().CloseClient(client);
324 11 : return err;
325 11 : }
326 :
327 5 : int32_t AdxRecvDevFileTimeout(
328 : AdxCommHandle handle, AdxString desPath, uint32_t timeout, AdxStringBuffer fileName, uint32_t fileNameLen)
329 : {
330 5 : IDE_CTRL_VALUE_FAILED(handle != nullptr, return IDE_DAEMON_ERROR, "handle is NULL.");
331 5 : IDE_CTRL_VALUE_FAILED(desPath != nullptr, return IDE_DAEMON_ERROR, "desPath is NULL.");
332 5 : IDE_CTRL_VALUE_FAILED(fileName != nullptr, return IDE_DAEMON_ERROR, "fileName is NULL.");
333 :
334 5 : uint32_t len = fileNameLen;
335 5 : int32_t ret = AdxRecvMsg(handle, &fileName, &len, timeout);
336 5 : if (ret != IDE_DAEMON_OK) {
337 1 : return ret;
338 : }
339 4 : std::string value(fileName);
340 4 : if (value.compare(HDC_END_MSG) == 0) {
341 1 : return IDE_DAEMON_ERROR;
342 : }
343 3 : value = std::string(desPath) + OS_SPLIT_STR + value;
344 3 : if (AdxCreateFileAndRecvValue(*handle, value) != IDE_DAEMON_OK) {
345 2 : return IDE_DAEMON_ERROR;
346 : }
347 1 : return IDE_DAEMON_OK;
348 4 : }
|