1 /*
2 * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "network/softbus/softbus_handler_asset.h"
17
18 #include <filesystem>
19 #include <fstream>
20 #include <memory>
21 #include <regex>
22 #include <sstream>
23 #include <unistd.h>
24
25 #include "all_connect/all_connect_manager.h"
26 #include "asset_callback_manager.h"
27 #include "device_manager.h"
28 #include "dfs_error.h"
29 #include "dm_device_info.h"
30 #include "ipc_skeleton.h"
31 #include "network/softbus/softbus_asset_recv_listener.h"
32 #include "network/softbus/softbus_asset_send_listener.h"
33 #include "network/softbus/softbus_permission_check.h"
34 #include "network/softbus/softbus_session_listener.h"
35 #include "network/softbus/softbus_session_pool.h"
36 #include "refbase.h"
37 #include "softbus_bus_center.h"
38 #include "utils_log.h"
39
40 namespace OHOS {
41 namespace Storage {
42 namespace DistributedFile {
43 using namespace OHOS::FileManagement;
44 constexpr size_t MAX_SIZE = 500;
45 constexpr size_t BUFFER_SIZE = 512;
46 const int32_t DFS_QOS_TYPE_MIN_BW = 90 * 1024 * 1024;
47 const int32_t DFS_QOS_TYPE_MAX_LATENCY = 10000;
48 const int32_t DFS_QOS_TYPE_MIN_LATENCY = 2000;
49 const std::string RELATIVE_PATH_FLAG = "/account/device_view/local/data/";
50 const std::string DST_BUNDLE_NAME_FLAG = "/";
51 const std::string TEMP_DIR = "ASSET_TEMP";
52 const std::string ASSET_POSTFIX_SINGLE = ".asset_single?";
53 const std::string ASSET_POSTFIX_ZIP = ".asset_zip?";
SoftBusHandlerAsset()54 SoftBusHandlerAsset::SoftBusHandlerAsset()
55 {
56 ISocketListener fileSendListener;
57 fileSendListener.OnBind = nullptr;
58 fileSendListener.OnShutdown = SoftBusAssetSendListener::OnSendShutdown;
59 fileSendListener.OnFile = SoftBusAssetSendListener::OnFile;
60 fileSendListener.OnBytes = nullptr;
61 fileSendListener.OnMessage = nullptr;
62 fileSendListener.OnQos = nullptr;
63 sessionListener_[DFS_ASSET_ROLE_SEND] = fileSendListener;
64
65 ISocketListener fileReceiveListener;
66 fileReceiveListener.OnBind = SoftbusAssetRecvListener::OnAssetRecvBind;
67 fileReceiveListener.OnShutdown = SoftbusAssetRecvListener::OnRecvShutdown;
68 fileReceiveListener.OnFile = SoftbusAssetRecvListener::OnFile;
69 fileReceiveListener.OnNegotiate2 = SoftBusAssetSendListener::OnNegotiate2;
70 fileReceiveListener.OnBytes = nullptr;
71 fileReceiveListener.OnMessage = nullptr;
72 fileReceiveListener.OnQos = nullptr;
73 sessionListener_[DFS_ASSET_ROLE_RECV] = fileReceiveListener;
74 }
75
76 SoftBusHandlerAsset::~SoftBusHandlerAsset() = default;
77
GetInstance()78 SoftBusHandlerAsset &SoftBusHandlerAsset::GetInstance()
79 {
80 LOGD("SoftBusHandlerAsset::GetInstance");
81 static SoftBusHandlerAsset assetHandle;
82 return assetHandle;
83 }
84
CreateAssetLocalSessionServer()85 void SoftBusHandlerAsset::CreateAssetLocalSessionServer()
86 {
87 LOGI("CreateAssetLocalSessionServer Enter.");
88 {
89 std::lock_guard<std::mutex> lock(serverIdMapMutex_);
90 if (serverIdMap_.find(ASSET_LOCAL_SESSION_NAME) != serverIdMap_.end()) {
91 LOGI("%s: Session already create.", ASSET_LOCAL_SESSION_NAME.c_str());
92 return;
93 }
94 }
95
96 SocketInfo serverInfo = {
97 .name = const_cast<char*>(ASSET_LOCAL_SESSION_NAME.c_str()),
98 .pkgName = const_cast<char*>(SERVICE_NAME.c_str()),
99 .dataType = DATA_TYPE_FILE,
100 };
101 int32_t socketId = Socket(serverInfo);
102 if (socketId < E_OK) {
103 LOGE("Create Socket fail socketId, socketId = %{public}d", socketId);
104 return;
105 }
106 QosTV qos[] = {
107 {.qos = QOS_TYPE_MIN_BW, .value = DFS_QOS_TYPE_MIN_BW},
108 {.qos = QOS_TYPE_MAX_LATENCY, .value = DFS_QOS_TYPE_MAX_LATENCY},
109 {.qos = QOS_TYPE_MIN_LATENCY, .value = DFS_QOS_TYPE_MIN_LATENCY},
110 };
111 int32_t ret = Listen(socketId, qos, sizeof(qos) / sizeof(qos[0]), &sessionListener_[DFS_ASSET_ROLE_RECV]);
112 if (ret != E_OK) {
113 LOGE("Listen SocketClient error");
114 Shutdown(socketId);
115 return;
116 }
117 SoftBusSessionPool::SessionInfo sessionInfo{.uid = IPCSkeleton::GetCallingUid()};
118 SoftBusSessionPool::GetInstance().AddSessionInfo(ASSET_LOCAL_SESSION_NAME, sessionInfo);
119 {
120 std::lock_guard<std::mutex> lock(serverIdMapMutex_);
121 serverIdMap_.insert(std::make_pair(ASSET_LOCAL_SESSION_NAME, socketId));
122 }
123 LOGI("CreateAssetLocalSessionServer Success.");
124 }
125
DeleteAssetLocalSessionServer()126 void SoftBusHandlerAsset::DeleteAssetLocalSessionServer()
127 {
128 LOGI("DeleteAssetLocalSessionServer Enter.");
129 std::lock_guard<std::mutex> lock(serverIdMapMutex_);
130 if (!serverIdMap_.empty()) {
131 auto it = serverIdMap_.find(ASSET_LOCAL_SESSION_NAME);
132 if (it == serverIdMap_.end()) {
133 LOGI("%s: Session already delete.", ASSET_LOCAL_SESSION_NAME.c_str());
134 return;
135 }
136 int32_t socketId = it->second;
137 serverIdMap_.erase(it);
138 Shutdown(socketId);
139 LOGI("RemoveSessionServer success.");
140 }
141 SoftBusSessionPool::GetInstance().DeleteSessionInfo(ASSET_LOCAL_SESSION_NAME);
142 }
143
AssetBind(const std::string & dstNetworkId,int32_t & socketId)144 int32_t SoftBusHandlerAsset::AssetBind(const std::string &dstNetworkId, int32_t &socketId)
145 {
146 if (!SoftBusPermissionCheck::CheckSrcPermission(dstNetworkId)) {
147 LOGI("Check src permission failed");
148 return E_PERMISSION_DENIED;
149 }
150 if (dstNetworkId.empty()) {
151 LOGI("The parameter is empty");
152 return E_OPEN_SESSION;
153 }
154 LOGI("AssetBind Enter.");
155 if (!SoftBusPermissionCheck::IsSameAccount(dstNetworkId)) {
156 LOGI("The source and sink device is not same account, not support.");
157 return E_OPEN_SESSION;
158 }
159 QosTV qos[] = {
160 {.qos = QOS_TYPE_MIN_BW, .value = DFS_QOS_TYPE_MIN_BW},
161 {.qos = QOS_TYPE_MAX_LATENCY, .value = DFS_QOS_TYPE_MAX_LATENCY},
162 {.qos = QOS_TYPE_MIN_LATENCY, .value = DFS_QOS_TYPE_MIN_LATENCY},
163 };
164 SocketInfo clientInfo = {
165 .name = const_cast<char*>((ASSET_LOCAL_SESSION_NAME.c_str())),
166 .peerName = const_cast<char*>(ASSET_LOCAL_SESSION_NAME.c_str()),
167 .peerNetworkId = const_cast<char*>(dstNetworkId.c_str()),
168 .pkgName = const_cast<char*>(SERVICE_NAME.c_str()),
169 .dataType = DATA_TYPE_FILE,
170 };
171
172 socketId = Socket(clientInfo);
173 if (socketId < E_OK) {
174 LOGE("Create OpenSoftbusChannel Socket error");
175 return E_OPEN_SESSION;
176 }
177 if (!SoftBusPermissionCheck::SetAccessInfoToSocket(socketId)) {
178 LOGE("Set access info faiLed");
179 Shutdown(socketId);
180 return E_OPEN_SESSION;
181 }
182
183 int32_t ret = Bind(socketId, qos, sizeof(qos) / sizeof(qos[0]), &sessionListener_[DFS_ASSET_ROLE_SEND]);
184 if (ret != E_OK) {
185 LOGE("Bind SocketClient error");
186 Shutdown(socketId);
187 return ret;
188 }
189 AllConnectManager::GetInstance().PublishServiceState(DfsConnectCode::PUSH_ASSET, dstNetworkId,
190 ServiceCollaborationManagerBussinessStatus::SCM_CONNECTED);
191 LOGI("OpenSession success.");
192 return E_OK;
193 }
194
AssetSendFile(int32_t socketId,const std::string & sendFile,bool isSingleFile)195 int32_t SoftBusHandlerAsset::AssetSendFile(int32_t socketId, const std::string& sendFile, bool isSingleFile)
196 {
197 auto assetObj = GetAssetObj(socketId);
198 if (assetObj == nullptr) {
199 LOGE("get assetObj fail.");
200 return ERR_BAD_VALUE;
201 }
202 if (!SoftBusPermissionCheck::IsSameAccount(assetObj->dstNetworkId_)) {
203 LOGI("The source and sink device is not same account, not support.");
204 return ERR_BAD_VALUE;
205 }
206
207 const char *src[MAX_SIZE] = {};
208 src[0] = sendFile.c_str();
209
210 auto dstFile = GetDstFile(sendFile, assetObj->srcBundleName_,
211 assetObj->dstBundleName_, assetObj->sessionId_, isSingleFile);
212 if (dstFile.empty()) {
213 LOGE("GetFileName failed or file is empty");
214 return ERR_BAD_VALUE;
215 }
216 const char *dst[MAX_SIZE] = {};
217 dst[0] = dstFile.c_str();
218
219 LOGI("AssetSendFile Enter.");
220 int32_t ret = ::SendFile(socketId, src, dst, 1);
221 if (ret != E_OK) {
222 LOGE("SendFile failed, sessionId = %{public}d", socketId);
223 return ret;
224 }
225 return E_OK;
226 }
227
closeAssetBind(int32_t socketId)228 void SoftBusHandlerAsset::closeAssetBind(int32_t socketId)
229 {
230 LOGI("closeAssetBind Enter.");
231 Shutdown(socketId);
232 auto assetObj = GetAssetObj(socketId);
233 if (assetObj == nullptr) {
234 return;
235 }
236 RemoveAssetObj(socketId);
237 AllConnectManager::GetInstance().PublishServiceState(DfsConnectCode::PUSH_ASSET, assetObj->dstNetworkId_,
238 ServiceCollaborationManagerBussinessStatus::SCM_IDLE);
239 }
240
OnAssetRecvBind(int32_t socketId,const std::string & srcNetWorkId)241 void SoftBusHandlerAsset::OnAssetRecvBind(int32_t socketId, const std::string &srcNetWorkId)
242 {
243 std::lock_guard<std::mutex> lock(clientInfoMutex_);
244 if (!SoftBusPermissionCheck::IsSameAccount(srcNetWorkId)) {
245 LOGE("The source and sink device is not same account, not support.");
246 Shutdown(socketId);
247 return;
248 }
249 clientInfoMap_.insert(std::make_pair(socketId, srcNetWorkId));
250 AllConnectManager::GetInstance().PublishServiceState(DfsConnectCode::PUSH_ASSET, srcNetWorkId,
251 ServiceCollaborationManagerBussinessStatus::SCM_CONNECTED);
252 }
253
GetClientInfo(int32_t socketId)254 std::string SoftBusHandlerAsset::GetClientInfo(int32_t socketId)
255 {
256 std::lock_guard<std::mutex> lock(clientInfoMutex_);
257 auto iter = clientInfoMap_.find(socketId);
258 if (iter == clientInfoMap_.end()) {
259 LOGE("ClientInfo not registered");
260 return "";
261 }
262 return iter->second;
263 }
264
GetSocketIdFromClientInfo(const std::string & peerNetworkId)265 std::vector<int32_t> SoftBusHandlerAsset::GetSocketIdFromClientInfo(const std::string &peerNetworkId)
266 {
267 std::vector<int32_t> socketIdVec;
268 std::lock_guard<std::mutex> lock(clientInfoMutex_);
269 for (auto iter = clientInfoMap_.begin(); iter != clientInfoMap_.end(); ++iter) {
270 if (iter->second == peerNetworkId) {
271 socketIdVec.push_back(iter->first);
272 }
273 }
274 return socketIdVec;
275 }
276
GetSocketIdFromAssetObj(const std::string & peerNetworkId)277 std::vector<int32_t> SoftBusHandlerAsset::GetSocketIdFromAssetObj(const std::string &peerNetworkId)
278 {
279 std::vector<int32_t> socketIdVec;
280 std::lock_guard<std::mutex> lock(assetObjMapMutex_);
281 for (auto iter = assetObjMap_.begin(); iter != assetObjMap_.end(); ++iter) {
282 if (iter->second->dstNetworkId_ == peerNetworkId) {
283 socketIdVec.push_back(iter->first);
284 }
285 }
286 return socketIdVec;
287 }
288
RemoveClientInfo(int32_t socketId)289 void SoftBusHandlerAsset::RemoveClientInfo(int32_t socketId)
290 {
291 auto peerNetworkId = GetClientInfo(socketId);
292 if (!peerNetworkId.empty()) {
293 AllConnectManager::GetInstance().PublishServiceState(DfsConnectCode::PUSH_ASSET, peerNetworkId,
294 ServiceCollaborationManagerBussinessStatus::SCM_IDLE);
295 }
296 RemoveAssetObj(socketId);
297 std::lock_guard<std::mutex> lock(clientInfoMutex_);
298 auto it = clientInfoMap_.find(socketId);
299 if (it != clientInfoMap_.end()) {
300 clientInfoMap_.erase(it->first);
301 }
302 }
303
AddAssetObj(int32_t socketId,const sptr<AssetObj> & assetObj)304 void SoftBusHandlerAsset::AddAssetObj(int32_t socketId, const sptr<AssetObj> &assetObj)
305 {
306 std::lock_guard<std::mutex> lock(assetObjMapMutex_);
307 auto iter = assetObjMap_.find(socketId);
308 if (iter != assetObjMap_.end()) {
309 LOGI("assetObj exist.");
310 return;
311 }
312 assetObjMap_.insert(std::pair<int32_t, sptr<AssetObj>>(socketId, assetObj));
313 }
314
GetAssetObj(int32_t socketId)315 sptr<AssetObj> SoftBusHandlerAsset::GetAssetObj(int32_t socketId)
316 {
317 std::lock_guard<std::mutex> lock(assetObjMapMutex_);
318 auto iter = assetObjMap_.find(socketId);
319 if (iter == assetObjMap_.end()) {
320 LOGE("AssetObj not exist");
321 return nullptr;
322 }
323
324 return iter->second;
325 }
326
RemoveAssetObj(int32_t socketId)327 void SoftBusHandlerAsset::RemoveAssetObj(int32_t socketId)
328 {
329 std::lock_guard<std::mutex> lock(assetObjMapMutex_);
330 auto iter = assetObjMap_.find(socketId);
331 if (iter != assetObjMap_.end()) {
332 assetObjMap_.erase(iter);
333 }
334 }
335
GenerateAssetObjInfo(int32_t socketId,const std::string & fileName,const sptr<AssetObj> & assetObj)336 int32_t SoftBusHandlerAsset::GenerateAssetObjInfo(int32_t socketId,
337 const std::string &fileName,
338 const sptr<AssetObj> &assetObj)
339 {
340 if (assetObj == nullptr) {
341 LOGE("assetObj is nullptr!");
342 return FileManagement::ERR_BAD_VALUE;
343 }
344
345 size_t pos = fileName.find(RELATIVE_PATH_FLAG);
346 if (pos == std::string::npos) {
347 LOGE("Generate dstBundleName fail");
348 return FileManagement::ERR_BAD_VALUE;
349 }
350 std::string relativeFileName = fileName.substr(pos + RELATIVE_PATH_FLAG.length());
351
352 pos = relativeFileName.find(DST_BUNDLE_NAME_FLAG);
353 if (pos == std::string::npos) {
354 LOGE("Generate dstBundleName fail");
355 return FileManagement::ERR_BAD_VALUE;
356 }
357 auto dstBundleName = relativeFileName.substr(0, pos);
358 assetObj->dstBundleName_ = dstBundleName;
359
360 std::smatch match;
361 std::regex sessionIdRegex("sessionId=([^&]+)");
362 if (!std::regex_search(fileName, match, sessionIdRegex)) {
363 LOGE("Generate sessionId fail");
364 return FileManagement::ERR_BAD_VALUE;
365 }
366 assetObj->sessionId_ = match[1].str();
367
368 std::regex srcBundleNameRegex("srcBundleName=([^&]+)");
369 if (!std::regex_search(fileName, match, srcBundleNameRegex)) {
370 LOGE("Generate srcBundleName fail");
371 return FileManagement::ERR_BAD_VALUE;
372 }
373 assetObj->srcBundleName_ = match[1].str();
374
375 assetObj->dstNetworkId_ = GetLocalNetworkId();
376 if (assetObj->dstNetworkId_.empty()) {
377 LOGE("Failed to get info of local devices");
378 return FileManagement::ERR_BAD_VALUE;
379 }
380 return FileManagement::ERR_OK;
381 }
382
GetDstFile(const std::string & file,const std::string & srcBundleName,const std::string & dstBundleName,const std::string & sessionId,bool isSingleFile)383 std::string SoftBusHandlerAsset::GetDstFile(const std::string &file,
384 const std::string &srcBundleName,
385 const std::string &dstBundleName,
386 const std::string &sessionId,
387 bool isSingleFile)
388 {
389 std::stringstream dstFile;
390 size_t pos = file.find(srcBundleName);
391 if (pos == std::string::npos) {
392 return "";
393 }
394 std::string tempDir;
395 if (isSingleFile) {
396 tempDir = ASSET_POSTFIX_SINGLE;
397 } else {
398 tempDir = ASSET_POSTFIX_ZIP;
399 }
400 dstFile << dstBundleName << "/" << TEMP_DIR << file.substr(pos + srcBundleName.length())
401 << tempDir << "srcBundleName=" << srcBundleName << "&sessionId=" << sessionId;
402
403 return dstFile.str();
404 }
405
GenerateUris(const std::vector<std::string> & fileList,const std::string & dstBundleName,bool isSingleFile)406 std::vector<std::string> SoftBusHandlerAsset::GenerateUris(const std::vector<std::string> &fileList,
407 const std::string &dstBundleName,
408 bool isSingleFile)
409 {
410 auto tempDir = dstBundleName + "/" + TEMP_DIR;
411 std::vector<std::string> uris;
412 if (isSingleFile) {
413 std::stringstream uri;
414 std::string file = fileList[0];
415 size_t posPrefix = file.find(tempDir);
416 if (posPrefix == std::string::npos) {
417 LOGE("not find tempDir in fileList.");
418 return {};
419 }
420 size_t posPostfix = file.find(ASSET_POSTFIX_SINGLE);
421 if (posPostfix == std::string::npos) {
422 LOGE("not find asset postfix in fileList.");
423 return {};
424 }
425 uri <<"file://" << dstBundleName << "/data/storage/el2/distributedfiles"
426 << file.substr(posPrefix + tempDir.length(), posPostfix - posPrefix - tempDir.length());
427 uris.emplace_back(uri.str());
428 return uris;
429 }
430 for (auto file : fileList) {
431 std::stringstream uri;
432 size_t posPrefix = file.find(tempDir);
433 if (posPrefix == std::string::npos) {
434 LOGE("not find tempDir in fileList.");
435 return {};
436 }
437 uri <<"file://" << dstBundleName << "/data/storage/el2/distributedfiles"
438 << file.substr(posPrefix + tempDir.length());
439 uris.emplace_back(uri.str());
440 }
441 return uris;
442 }
443
CompressFile(const std::vector<std::string> & fileList,const std::string & relativePath,const std::string & zipFileName)444 int32_t SoftBusHandlerAsset::CompressFile(const std::vector<std::string> &fileList,
445 const std::string &relativePath,
446 const std::string &zipFileName)
447 {
448 LOGI("CompressFile begin.");
449 zipFile outputFile = zipOpen64(zipFileName.c_str(), APPEND_STATUS_CREATE);
450 if (!outputFile) {
451 LOGE("Minizip failed to zipOpen");
452 return E_ZIP;
453 }
454
455 for (const std::string& rootFile : fileList) {
456 size_t pos = rootFile.find(relativePath);
457 if (pos == std::string::npos) {
458 LOGE("rootFile not have relativePath");
459 return E_ZIP;
460 }
461 auto file = rootFile.substr(pos + relativePath.length());
462
463 int err = zipOpenNewFileInZip3_64(outputFile, file.c_str(), NULL, NULL, 0, NULL, 0, NULL,
464 Z_DEFLATED, 0, 0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0, 0);
465 if (err != ZIP_OK) {
466 LOGE("Minizip failed to zipOpenNewFileInZip");
467 zipClose(outputFile, NULL);
468 return E_ZIP;
469 }
470
471 FILE* f = fopen(rootFile.c_str(), "rb");
472 if (f == NULL) {
473 LOGE("open file fail");
474 return E_ZIP;
475 }
476 const size_t pageSize { getpagesize() };
477 auto buf = std::make_unique<char[]>(pageSize);
478 size_t actLen;
479 do {
480 actLen = fread(buf.get(), 1, pageSize, f);
481 if (actLen > 0) {
482 zipWriteInFileInZip(outputFile, buf.get(), actLen);
483 }
484 } while (actLen == pageSize);
485 if (fclose(f) != 0) {
486 LOGE("Minizip failed to fclose");
487 }
488 zipCloseFileInZip(outputFile);
489 }
490 zipClose(outputFile, NULL);
491 LOGI("CompressFile end.");
492 return E_OK;
493 }
494
DecompressFile(const std::string & unZipFileName,const std::string & relativePath)495 std::vector<std::string> SoftBusHandlerAsset::DecompressFile(const std::string &unZipFileName,
496 const std::string &relativePath)
497 {
498 LOGI("DecompressFile begin.");
499 if (!IsDir(relativePath)) {
500 MkDirRecurse(relativePath, S_IRWXU | S_IRWXG | S_IXOTH);
501 }
502
503 unzFile zipFile = unzOpen64(unZipFileName.c_str());
504 if (!zipFile) {
505 LOGE("Minizip failed to unzOpen");
506 return {};
507 }
508
509 unz_global_info64 globalInfo;
510 if (unzGetGlobalInfo64(zipFile, &globalInfo) != UNZ_OK) {
511 unzClose(zipFile);
512 LOGE("Minizip failed to unzGetGlobalInfo");
513 return {};
514 }
515
516 std::vector<std::string> fileList;
517
518 for (size_t i = 0; i < globalInfo.number_entry; ++i) {
519 std::string filePath = ExtractFile(zipFile, relativePath.c_str());
520 if (!filePath.empty()) {
521 fileList.push_back(filePath);
522 }
523 unzCloseCurrentFile(zipFile);
524 unzGoToNextFile(zipFile);
525 }
526 unzClose(zipFile);
527 LOGI("DecompressFile end.");
528 return fileList;
529 }
530
GetLocalNetworkId()531 std::string SoftBusHandlerAsset::GetLocalNetworkId()
532 {
533 NodeBasicInfo tmpNodeInfo;
534 int errCode = GetLocalNodeDeviceInfo(SERVICE_NAME.c_str(), &tmpNodeInfo);
535 if (errCode != 0) {
536 LOGE("Failed to get info of local devices");
537 return "";
538 }
539 return tmpNodeInfo.networkId;
540 }
541
MkDir(const std::string & path,mode_t mode)542 int32_t SoftBusHandlerAsset::MkDir(const std::string &path, mode_t mode)
543 {
544 return TEMP_FAILURE_RETRY(mkdir(path.c_str(), mode));
545 }
546
MkDirRecurse(const std::string & path,mode_t mode)547 bool SoftBusHandlerAsset::MkDirRecurse(const std::string& path, mode_t mode)
548 {
549 size_t pos = path.rfind("/");
550 if (pos == std::string::npos) {
551 LOGE("is not a dir");
552 }
553 auto dirPath = path.substr(0, pos);
554
555 std::string::size_type index = 0;
556 do {
557 std::string subPath = dirPath;
558 index = path.find('/', index + 1);
559 if (index != std::string::npos) {
560 subPath = path.substr(0, index);
561 }
562
563 if (TEMP_FAILURE_RETRY(access(subPath.c_str(), F_OK)) != 0) {
564 if (MkDir(subPath, mode) != 0 && errno != EEXIST) {
565 return false;
566 }
567 }
568 } while (index != std::string::npos);
569
570 return TEMP_FAILURE_RETRY(access(path.c_str(), F_OK)) == 0;
571 }
572
IsDir(const std::string & path)573 bool SoftBusHandlerAsset::IsDir(const std::string &path)
574 {
575 // check whether the path exists
576 struct stat st;
577 int ret = TEMP_FAILURE_RETRY(lstat(path.c_str(), &st));
578 if (ret) {
579 return false;
580 }
581 return S_ISDIR(st.st_mode);
582 }
583
ExtractFile(unzFile unZipFile,const std::string & dir)584 std::string SoftBusHandlerAsset::ExtractFile(unzFile unZipFile, const std::string &dir)
585 {
586 auto filename = std::make_unique<char[]>(BUFFER_SIZE);
587 unz_file_info64 fileInfo;
588 if (unzGetCurrentFileInfo64(unZipFile, &fileInfo, filename.get(), BUFFER_SIZE, NULL, 0, NULL, 0) != UNZ_OK) {
589 LOGE("Minizip failed to unzGetCurrentFileInfo64");
590 return "";
591 }
592 std::string filenameWithPath(filename.get());
593 filenameWithPath = dir + filenameWithPath;
594 size_t pos = filenameWithPath.rfind('/');
595 if (pos == std::string::npos) {
596 LOGE("file path error");
597 return "";
598 }
599 std::string filenameWithoutPath = filenameWithPath.substr(pos + 1);
600
601 if (!IsDir(filenameWithPath)) {
602 MkDirRecurse(filenameWithPath, S_IRWXU | S_IRWXG | S_IXOTH);
603 }
604 if (unzOpenCurrentFile(unZipFile) != UNZ_OK) {
605 LOGE("Minizip failed to unzOpenCurrentFile");
606 }
607 std::fstream file;
608 file.open(filenameWithPath, std::ios_base::out | std::ios_base::binary);
609 if (!file.is_open()) {
610 LOGE("open zip file fail");
611 return "";
612 }
613 const size_t pageSize = { getpagesize() };
614 auto fileData = std::make_unique<char[]>(pageSize);
615 int32_t bytesRead;
616 do {
617 bytesRead = unzReadCurrentFile(unZipFile, (voidp)fileData.get(), pageSize);
618 if (bytesRead < 0) {
619 LOGE("Minizip failed to unzReadCurrentFile");
620 file.close();
621 return "";
622 }
623 file.write(fileData.get(), bytesRead);
624 } while (bytesRead > 0);
625 file.close();
626 return filenameWithPath;
627 }
628
RemoveFile(const std::string & path,bool isRemove)629 void SoftBusHandlerAsset::RemoveFile(const std::string &path, bool isRemove)
630 {
631 LOGI("RemoveFile path start");
632 if (!isRemove) {
633 LOGI("this file is not need remove");
634 return;
635 }
636 bool ret = std::filesystem::remove(path.c_str());
637 if (!ret) {
638 LOGE("remove file fail");
639 }
640 }
641 } // namespace DistributedFile
642 } // namespace Storage
643 } // namespace OHOS