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