• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "translistener.h"
17 #include <filesystem>
18 #include <random>
19 #include <thread>
20 #include "sandbox_helper.h"
21 #include "uri.h"
22 #include "uni_error.h"
23 
24 using Uri = OHOS::Uri;
25 namespace OHOS {
26 namespace CJSystemapi {
27 using namespace FileFs;
28 const std::string NETWORK_PARA = "?networkid=";
29 const std::string FILE_MANAGER_AUTHORITY = "docs";
30 const std::string MEDIA_AUTHORITY = "media";
31 const std::string DISTRIBUTED_PATH = "/data/storage/el2/distributedfiles/";
32 
RmDir(const std::string & path)33 void TransListener::RmDir(const std::string &path)
34 {
35     LOGI("RmDirm path : %{public}s", path.c_str());
36     std::filesystem::path pathName(path);
37     std::error_code errCode;
38     if (std::filesystem::exists(pathName, errCode)) {
39         std::filesystem::remove_all(pathName, errCode);
40         if (errCode.value() != 0) {
41             LOGE("Failed to remove directory, error code: %{public}d", errCode.value());
42         }
43     } else {
44         LOGE("pathName is not exists, error code: %{public}d", errCode.value());
45     }
46 }
47 
CreateDfsCopyPath()48 std::string TransListener::CreateDfsCopyPath()
49 {
50     std::random_device rd;
51     std::string random = std::to_string(rd());
52     while (std::filesystem::exists(DISTRIBUTED_PATH + random)) {
53         random = std::to_string(rd());
54     }
55     return random;
56 }
57 
CopyFileFromSoftBus(const std::string & srcUri,const std::string & destUri,std::shared_ptr<FileInfos> fileInfos,std::shared_ptr<CjCallbackObject> callback)58 int32_t TransListener::CopyFileFromSoftBus(const std::string& srcUri, const std::string& destUri,
59     std::shared_ptr<FileInfos> fileInfos, std::shared_ptr<CjCallbackObject> callback)
60 {
61     LOGI("CopyFileFromSoftBus begin.");
62     sptr<TransListener> transListener = new (std::nothrow) TransListener();
63     if (transListener == nullptr) {
64         LOGE("new trans listener failed");
65         return ENOMEM;
66     }
67     transListener->callback_ = std::move(callback);
68     Storage::DistributedFile::HmdfsInfo info{};
69     Uri uri(destUri);
70     info.authority = uri.GetAuthority();
71     info.sandboxPath = AppFileService::SandboxHelper::Decode(uri.GetPath());
72     std::string disSandboxPath;
73     auto ret = PrepareCopySession(srcUri, destUri, transListener, info, disSandboxPath);
74     if (ret != 0) {
75         LOGE("PrepareCopySession failed, ret = %{public}d.", ret);
76         return EIO;
77     }
78     if (fileInfos->taskSignal != nullptr) {
79         fileInfos->taskSignal->SetFileInfoOfRemoteTask(info.sessionName, fileInfos->srcPath);
80     }
81     std::unique_lock<std::mutex> lock(transListener->cvMutex_);
82     transListener->cv_.wait(lock, [&transListener]() {
83         return transListener->copyEvent_.copyResult == SUCCESS ||
84             transListener->copyEvent_.copyResult == FAILED;
85     });
86     LOGI("dfs PrepareSession Finish, result is %{public}d", transListener->copyEvent_.copyResult);
87     if (transListener->copyEvent_.copyResult == FAILED) {
88         if (info.authority != FILE_MANAGER_AUTHORITY && info.authority != MEDIA_AUTHORITY) {
89             RmDir(disSandboxPath);
90         }
91         auto it = softbusErr2ErrCodeTable.find(transListener->copyEvent_.errorCode);
92         if (it == softbusErr2ErrCodeTable.end()) {
93             return EIO;
94         }
95         return it->second;
96     }
97     if (info.authority == FILE_MANAGER_AUTHORITY || info.authority == MEDIA_AUTHORITY) {
98         LOGE("Public or media path not copy");
99         return 0;
100     }
101     ret = CopyToSandBox(srcUri, disSandboxPath, info.sandboxPath);
102     RmDir(disSandboxPath);
103     if (ret != 0) {
104         LOGE("CopyToSandBox failed, ret = %{public}d.", ret);
105         return EIO;
106     }
107     return 0;
108 }
109 
PrepareCopySession(const std::string & srcUri,const std::string & destUri,TransListener * transListener,Storage::DistributedFile::HmdfsInfo & info,std::string & disSandboxPath)110 int32_t TransListener::PrepareCopySession(const std::string &srcUri,
111                                           const std::string &destUri,
112                                           TransListener* transListener,
113                                           Storage::DistributedFile::HmdfsInfo &info,
114                                           std::string &disSandboxPath)
115 {
116     std::string tmpDir;
117     if (info.authority != FILE_MANAGER_AUTHORITY && info.authority  != MEDIA_AUTHORITY) {
118         tmpDir = CreateDfsCopyPath();
119         disSandboxPath = DISTRIBUTED_PATH + tmpDir;
120         std::error_code errCode;
121         if (!std::filesystem::create_directory(disSandboxPath, errCode)) {
122             LOGE("Create dir failed, error code: %{public}d", errCode.value());
123             return errCode.value();
124         }
125 
126         auto pos = info.sandboxPath.rfind('/');
127         if (pos == std::string::npos) {
128             LOGE("invalid file path");
129             return EIO;
130         }
131         auto sandboxDir = info.sandboxPath.substr(0, pos);
132         if (std::filesystem::exists(sandboxDir, errCode)) {
133             info.dirExistFlag = true;
134         }
135     }
136 
137     info.copyPath = tmpDir;
138     auto networkId = GetNetworkIdFromUri(srcUri);
139     LOGI("dfs PrepareSession begin.");
140     auto ret = Storage::DistributedFile::DistributedFileDaemonManager::GetInstance().PrepareSession(srcUri, destUri,
141         networkId, transListener, info);
142     if (ret != ERRNO_NOERR) {
143         LOGE("PrepareSession failed, ret = %{public}d.", ret);
144         if (info.authority != FILE_MANAGER_AUTHORITY && info.authority != MEDIA_AUTHORITY) {
145             RmDir(disSandboxPath);
146         }
147         return EIO;
148     }
149     return ERRNO_NOERR;
150 }
151 
CopyToSandBox(const std::string & srcUri,const std::string & disSandboxPath,const std::string & sandboxPath)152 int32_t TransListener::CopyToSandBox(const std::string &srcUri, const std::string &disSandboxPath,
153     const std::string &sandboxPath)
154 {
155     std::error_code errCode;
156     if (std::filesystem::exists(sandboxPath) && std::filesystem::is_directory(sandboxPath)) {
157         LOGI("Copy dir");
158         std::filesystem::copy(disSandboxPath, sandboxPath,
159             std::filesystem::copy_options::recursive | std::filesystem::copy_options::update_existing, errCode);
160         if (errCode.value() != 0) {
161             LOGE("Copy dir failed: errCode: %{public}d", errCode.value());
162             return EIO;
163         }
164     } else {
165         LOGI("Copy file.");
166         Uri uri(srcUri);
167         auto fileName = GetFileName(uri.GetPath());
168         if (fileName.empty()) {
169             LOGE("Get filename failed");
170             RmDir(disSandboxPath);
171             return EIO;
172         }
173         std::filesystem::copy(disSandboxPath + fileName, sandboxPath, std::filesystem::copy_options::update_existing,
174             errCode);
175         if (errCode.value() != 0) {
176             LOGE("Copy file failed: errCode: %{public}d", errCode.value());
177             return EIO;
178         }
179     }
180     LOGI("Copy file success.");
181     return ERRNO_NOERR;
182 }
183 
GetFileName(const std::string & path)184 std::string TransListener::GetFileName(const std::string &path)
185 {
186     auto pos = path.find_last_of('/');
187     if (pos == std::string::npos) {
188         LOGE("invalid path");
189         return "";
190     }
191     return AppFileService::SandboxHelper::Decode(path.substr(pos));
192 }
193 
GetNetworkIdFromUri(const std::string & uri)194 std::string TransListener::GetNetworkIdFromUri(const std::string &uri)
195 {
196     return uri.substr(uri.find(NETWORK_PARA) + NETWORK_PARA.size(), uri.size());
197 }
198 
CallbackComplete(TransListener * transListener,CProgress progress)199 void TransListener::CallbackComplete(TransListener* transListener, CProgress progress)
200 {
201     if (transListener == nullptr ||
202         transListener->callback_ == nullptr ||
203         transListener->callback_->callback == nullptr) {
204         LOGE("Failed to get copy progress callback.");
205         return;
206     }
207     transListener->callback_->callback(progress);
208 }
209 
OnFileReceive(uint64_t totalBytes,uint64_t processedBytes)210 int32_t TransListener::OnFileReceive(uint64_t totalBytes, uint64_t processedBytes)
211 {
212     std::lock_guard<std::mutex> lock(callbackMutex_);
213     if (callback_ == nullptr) {
214         LOGE("Failed to parse watcher callback");
215         return ENOMEM;
216     }
217     CProgress progress = { .processedSize = processedBytes, .totalSize = totalBytes };
218     std::thread([this, progress]() {
219         CallbackComplete(this, progress);
220     }).detach();
221     return ERRNO_NOERR;
222 }
223 
OnFinished(const std::string & sessionName)224 int32_t TransListener::OnFinished(const std::string &sessionName)
225 {
226     LOGI("OnFinished");
227     {
228         std::lock_guard<std::mutex> lock(callbackMutex_);
229         callback_ = nullptr;
230     }
231     copyEvent_.copyResult = SUCCESS;
232     cv_.notify_all();
233     return ERRNO_NOERR;
234 }
235 
OnFailed(const std::string & sessionName,int32_t errorCode)236 int32_t TransListener::OnFailed(const std::string &sessionName, int32_t errorCode)
237 {
238     LOGI("OnFailed, errorCode is %{public}d", errorCode);
239     {
240         std::lock_guard<std::mutex> lock(callbackMutex_);
241         callback_ = nullptr;
242     }
243     copyEvent_.copyResult = FAILED;
244     copyEvent_.errorCode = errorCode;
245     cv_.notify_all();
246     return ERRNO_NOERR;
247 }
248 }
249 }
250