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