1 /*
2 * Copyright (c) 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 "copy/file_copy_manager.h"
17
18 #include <cstring>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <filesystem>
22 #include <limits>
23 #include <memory>
24 #include <sstream>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28
29 #include "accesstoken_kit.h"
30 #include "bundle_mgr_client.h"
31 #include "bundle_mgr_interface.h"
32 #include "copy/distributed_file_fd_guard.h"
33 #include "copy/file_copy_listener.h"
34 #include "copy/file_size_utils.h"
35 #include "datashare_helper.h"
36 #include "dfs_error.h"
37 #include "distributed_file_daemon_proxy.h"
38 #include "file_uri.h"
39 #include "if_system_ability_manager.h"
40 #include "ipc_skeleton.h"
41 #include "iservice_registry.h"
42 #include "iremote_stub.h"
43 #include "sandbox_helper.h"
44 #include "system_ability_definition.h"
45 #include "utils_log.h"
46
47 #undef LOG_DOMAIN
48 #undef LOG_TAG
49 #define LOG_DOMAIN 0xD004315
50 #define LOG_TAG "distributedfile_daemon"
51
52 namespace OHOS {
53 namespace Storage {
54 namespace DistributedFile {
55 using namespace AppFileService;
56 using namespace FileManagement;
57 static const std::string FILE_PREFIX_NAME = "file://";
58 static const std::string NETWORK_PARA = "?networkid=";
59 static const std::string MEDIALIBRARY_DATA_URI = "datashare:///media";
60 static const std::string MTP_PATH_PREFIX = "/storage/External/mtp";
61 static const std::string MEDIA = "media";
62 static constexpr size_t MAX_SIZE = 1024 * 1024 * 4;
63 static const int OPEN_TRUC_VERSION = 20;
64 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) && !defined(CROSS_PLATFORM)
65 const uint32_t API_VERSION_MOD = 1000;
66 #endif
67 std::shared_ptr<FileCopyManager> FileCopyManager::instance_ = nullptr;
68 uint32_t g_apiCompatibleVersion = 0;
69
70 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) && !defined(CROSS_PLATFORM)
IsNumeric(const std::string & str)71 bool IsNumeric(const std::string &str)
72 {
73 if (str.empty()) {
74 return false;
75 }
76 for (char const &c : str) {
77 if (!isdigit(c)) {
78 return false;
79 }
80 }
81 return true;
82 }
83
SetQueryMap(Uri * uri,std::unordered_map<std::string,std::string> & queryMap)84 void SetQueryMap(Uri* uri, std::unordered_map<std::string,
85 std::string> &queryMap)
86 {
87 // file://media/image/12?networkid=xxxx&api_version=xxxx?times=xxx&user=101
88 std::string query = uri->GetQuery();
89 std::string pairString;
90 std::stringstream queryStream(query);
91
92 while (getline(queryStream, pairString, '&')) {
93 size_t splitIndex = pairString.find('=');
94 if (splitIndex == std::string::npos || splitIndex == (pairString.length() - 1)) {
95 LOGE("failed to parse query!");
96 continue;
97 }
98 queryMap[pairString.substr(0, splitIndex)] = pairString.substr(splitIndex + 1);
99 }
100 return;
101 }
102
GetAndCheckUserId(Uri * uri,std::string & userId)103 bool GetAndCheckUserId(Uri* uri, std::string &userId)
104 {
105 if (uri->ToString().find("user=") == std::string::npos) {
106 return false;
107 }
108
109 std::unordered_map<std::string, std::string> queryMap;
110 SetQueryMap(uri, queryMap);
111 auto it = queryMap.find("user");
112 if (it != queryMap.end()) {
113 userId = it->second;
114 if (!IsNumeric(userId)) {
115 LOGE("IsNumeric check fail");
116 return false;
117 }
118 return true;
119 } else {
120 LOGE("GetAndCheckUserId no match userId");
121 }
122 return false;
123 }
124
125 /*
126 * For compatibility considerations, filtering system applications require non permission verification
127 */
IsSystemApp()128 bool IsSystemApp()
129 {
130 uint64_t fullTokenId = IPCSkeleton::GetSelfTokenID();
131 return Security::AccessToken::AccessTokenKit::IsSystemAppByFullTokenID(fullTokenId);
132 }
133
GetApiCompatibleVersion()134 uint32_t GetApiCompatibleVersion()
135 {
136 uint32_t apiCompatibleVersion = 0;
137 OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
138 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
139 if (systemAbilityManager == nullptr) {
140 LOGE("systemAbilityManager is null");
141 return apiCompatibleVersion;
142 }
143
144 OHOS::sptr<OHOS::IRemoteObject> remoteObject =
145 systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
146 if (remoteObject == nullptr) {
147 LOGE("remoteObject is null");
148 return apiCompatibleVersion;
149 }
150
151 sptr<AppExecFwk::IBundleMgr> iBundleMgr = OHOS::iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
152 if (iBundleMgr == nullptr) {
153 LOGE("IBundleMgr is null");
154 return apiCompatibleVersion;
155 }
156
157 AppExecFwk::BundleInfo bundleInfo;
158 auto res = iBundleMgr->GetBundleInfoForSelf(0, bundleInfo);
159 if (res == E_OK) {
160 apiCompatibleVersion = bundleInfo.targetVersion % API_VERSION_MOD;
161 } else {
162 LOGE("Call for GetApiCompatibleVersion failed, err:%{public}d", res);
163 }
164 return apiCompatibleVersion;
165 }
166 #endif
167
GetInstance()168 std::shared_ptr<FileCopyManager> FileCopyManager::GetInstance()
169 {
170 static std::once_flag once;
171 std::call_once(once, []() {
172 FileCopyManager::instance_ = std::make_shared<FileCopyManager>();
173 });
174
175 return instance_;
176 }
177
Copy(const std::string & srcUri,const std::string & destUri,ProcessCallback & processCallback)178 int32_t FileCopyManager::Copy(const std::string &srcUri, const std::string &destUri, ProcessCallback &processCallback)
179 {
180 LOGE("FileCopyManager Copy start");
181 if (srcUri.empty() || destUri.empty()) {
182 return EINVAL;
183 }
184 if (srcUri == destUri) {
185 LOGE("The srcUri and destUri is same");
186 return EINVAL;
187 }
188
189 if (!FileSizeUtils::IsFilePathValid(FileSizeUtils::GetRealUri(srcUri)) ||
190 !FileSizeUtils::IsFilePathValid(FileSizeUtils::GetRealUri(destUri))) {
191 LOGE("path is forbidden");
192 return EINVAL;
193 }
194 auto infos = std::make_shared<FileInfos>();
195 CreateFileInfos(srcUri, destUri, infos);
196 if (IsRemoteUri(infos->srcUri)) {
197 auto ret = ExecRemote(infos, processCallback);
198 RemoveFileInfos(infos);
199 return ret;
200 }
201 infos->localListener = FileCopyLocalListener::GetLocalListener(infos->srcPath,
202 infos->srcUriIsFile, processCallback);
203 auto result = ExecLocal(infos);
204 RemoveFileInfos(infos);
205 infos->localListener->StopListener();
206 LOGE("FileCopyManager Copy end");
207 if (result != E_OK) {
208 return result;
209 }
210 return infos->localListener->GetResult();
211 }
212
ExecRemote(std::shared_ptr<FileInfos> infos,ProcessCallback & processCallback)213 int32_t FileCopyManager::ExecRemote(std::shared_ptr<FileInfos> infos, ProcessCallback &processCallback)
214 {
215 LOGI("ExecRemote Copy start ");
216 sptr<TransListener> transListener (new (std::nothrow) TransListener(infos->destUri, processCallback));
217 if (transListener == nullptr) {
218 LOGE("new trans listener failed");
219 return ENOMEM;
220 }
221 infos->transListener = transListener;
222
223 auto networkId = transListener->GetNetworkIdFromUri(infos->srcUri);
224 auto distributedFileDaemonProxy = DistributedFileDaemonProxy::GetInstance();
225 if (distributedFileDaemonProxy == nullptr) {
226 LOGE("proxy is null");
227 return E_SA_LOAD_FAILED;
228 }
229 auto ret = distributedFileDaemonProxy->PrepareSession(infos->srcUri, infos->destUri,
230 networkId, transListener, transListener->hmdfsInfo_);
231 if (ret != E_OK) {
232 LOGE("PrepareSession failed, ret = %{public}d.", ret);
233 return ret;
234 }
235
236 auto copyResult = transListener->WaitForCopyResult();
237 if (copyResult == DFS_FAILED) {
238 return transListener->GetErrCode();
239 }
240 return transListener->CopyToSandBox(infos->srcUri);
241 }
242
Cancel(const bool isKeepFiles)243 int32_t FileCopyManager::Cancel(const bool isKeepFiles)
244 {
245 LOGI("Cancel all Copy");
246 std::lock_guard<std::mutex> lock(FileInfosVecMutex_);
247 for (auto &item : FileInfosVec_) {
248 item->needCancel.store(true);
249 if (item->transListener != nullptr) {
250 LOGE("Cancel.");
251 item->transListener->Cancel(item->srcUri, item->destUri);
252 }
253 if (!isKeepFiles) {
254 DeleteResFile(item);
255 }
256 }
257 FileInfosVec_.clear();
258 return E_OK;
259 }
260
Cancel(const std::string & srcUri,const std::string & destUri,const bool isKeepFiles)261 int32_t FileCopyManager::Cancel(const std::string &srcUri, const std::string &destUri, const bool isKeepFiles)
262 {
263 LOGI("Cancel Copy");
264 std::lock_guard<std::mutex> lock(FileInfosVecMutex_);
265 int32_t ret = 0;
266 if (!FileSizeUtils::IsFilePathValid(FileSizeUtils::GetRealUri(srcUri)) ||
267 !FileSizeUtils::IsFilePathValid(FileSizeUtils::GetRealUri(destUri))) {
268 LOGE("path is forbidden");
269 return EINVAL;
270 }
271 for (auto item = FileInfosVec_.begin(); item != FileInfosVec_.end();) {
272 if ((*item)->srcUri != srcUri || (*item)->destUri != destUri) {
273 ++item;
274 continue;
275 }
276 (*item)->needCancel.store(true);
277 if ((*item)->transListener != nullptr) {
278 LOGE("Cancel");
279 ret = (*item)->transListener->Cancel(srcUri, destUri);
280 }
281 if (!isKeepFiles) {
282 DeleteResFile(*item);
283 }
284 item = FileInfosVec_.erase(item);
285 return ret;
286 }
287 return E_OK;
288 }
289
DeleteResFile(std::shared_ptr<FileInfos> infos)290 void FileCopyManager::DeleteResFile(std::shared_ptr<FileInfos> infos)
291 {
292 LOGI("start DeleteResFile");
293 std::error_code errCode;
294 //delete files in remote cancel
295 if (infos->transListener != nullptr) {
296 if (std::filesystem::exists(infos->destPath, errCode)) {
297 std::filesystem::remove(infos->destPath, errCode);
298 }
299 return;
300 }
301
302 //delete files&dirs in local cancel
303 if (infos->localListener == nullptr) {
304 LOGE("local listener is nullptr");
305 return;
306 }
307 auto filePaths = infos->localListener->GetFilePath();
308 for (auto path : filePaths) {
309 if (!std::filesystem::exists(path, errCode)) {
310 LOGE("Failed to find the file, errcode %{public}d", errCode.value());
311 continue;
312 }
313 std::filesystem::remove(path, errCode);
314 }
315
316 std::lock_guard<std::mutex> lock(infos->subDirsMutex);
317 for (auto subDir : infos->subDirs) {
318 if (!std::filesystem::exists(subDir, errCode)) {
319 LOGE("Failed to find the dir, errcode %{public}d", errCode.value());
320 continue;
321 }
322 std::filesystem::remove(subDir, errCode);
323 }
324 }
325
IsDirectory(const std::string & path)326 bool FileCopyManager::IsDirectory(const std::string &path)
327 {
328 struct stat buf {};
329 int ret = stat(path.c_str(), &buf);
330 if (ret == -1) {
331 LOGE("stat failed, errno is %{public}d", errno);
332 return false;
333 }
334 return (buf.st_mode & S_IFMT) == S_IFDIR;
335 }
336
IsFile(const std::string & path)337 bool FileCopyManager::IsFile(const std::string &path)
338 {
339 struct stat buf {};
340 int ret = stat(path.c_str(), &buf);
341 if (ret == -1) {
342 LOGE("stat failed, errno is %{public}d, ", errno);
343 return false;
344 }
345 return (buf.st_mode & S_IFMT) == S_IFREG;
346 }
347
ExecCopy(std::shared_ptr<FileInfos> infos)348 int32_t FileCopyManager::ExecCopy(std::shared_ptr<FileInfos> infos)
349 {
350 if (infos == nullptr) {
351 LOGE("infos is nullptr");
352 return EINVAL;
353 }
354 if (infos->srcUriIsFile && IsFile(infos->destPath)) {
355 // copy file
356 return CopyFile(infos->srcPath, infos->destPath, infos);
357 }
358 if (!infos->srcUriIsFile && IsDirectory(infos->destPath)) {
359 if (infos->srcPath.back() != '/') {
360 infos->srcPath += '/';
361 }
362 if (infos->destPath.back() != '/') {
363 infos->destPath += '/';
364 }
365 // copyDir
366 return CopyDirFunc(infos->srcPath, infos->destPath, infos);
367 }
368 LOGI("ExecLocal not support this srcUri and destUri");
369 return EINVAL;
370 }
371
ExecLocal(std::shared_ptr<FileInfos> infos)372 int32_t FileCopyManager::ExecLocal(std::shared_ptr<FileInfos> infos)
373 {
374 LOGI("start ExecLocal");
375 if (infos == nullptr || infos->localListener == nullptr) {
376 LOGE("infos or localListener is nullptr");
377 return EINVAL;
378 }
379 if (infos->srcUriIsFile) {
380 if (infos->srcPath == infos->destPath) {
381 LOGE("The src and dest is same");
382 return EINVAL;
383 }
384 int32_t ret = CheckOrCreatePath(infos->destPath);
385 if (ret != E_OK) {
386 LOGE("check or create fail, error code is %{public}d", ret);
387 return ret;
388 }
389 }
390 auto ret = infos->localListener->AddListenerFile(infos->srcPath, infos->destPath, IN_MODIFY);
391 if (ret != E_OK) {
392 LOGE("AddListenerFile fail, errno = %{public}d", ret);
393 return ret;
394 }
395 infos->localListener->StartListener();
396 return ExecCopy(infos);
397 }
398
CopyFile(const std::string & src,const std::string & dest,std::shared_ptr<FileInfos> infos)399 int32_t FileCopyManager::CopyFile(const std::string &src, const std::string &dest, std::shared_ptr<FileInfos> infos)
400 {
401 LOGI("CopyFile start");
402 infos->localListener->AddFile(dest);
403 int32_t srcFd = -1;
404 int32_t ret = OpenSrcFile(src, infos, srcFd);
405 if (srcFd < 0) {
406 return ret;
407 }
408 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) && !defined(CROSS_PLATFORM)
409 if (g_apiCompatibleVersion == 0) {
410 g_apiCompatibleVersion = GetApiCompatibleVersion();
411 }
412 #endif
413
414 int32_t destFd = -1;
415 if (g_apiCompatibleVersion >= OPEN_TRUC_VERSION) {
416 destFd = open(dest.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
417 } else {
418 destFd = open(dest.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
419 }
420 if (destFd < 0) {
421 LOGE("Error opening dest file descriptor. errno = %{public}d", errno);
422 close(srcFd);
423 return errno;
424 }
425 std::shared_ptr<FDGuard> srcFdg = std::make_shared<FDGuard>(srcFd, true);
426 std::shared_ptr<FDGuard> destFdg = std::make_shared<FDGuard>(destFd, true);
427 if (srcFdg == nullptr || destFdg == nullptr) {
428 LOGE("Failed to request heap memory.");
429 close(srcFd);
430 close(destFd);
431 return ENOMEM;
432 }
433 return SendFileCore(srcFdg, destFdg, infos);
434 }
435
fs_req_cleanup(uv_fs_t * req)436 void fs_req_cleanup(uv_fs_t* req)
437 {
438 uv_fs_req_cleanup(req);
439 if (req) {
440 delete req;
441 req = nullptr;
442 }
443 }
444
SendFileCore(std::shared_ptr<FDGuard> srcFdg,std::shared_ptr<FDGuard> destFdg,std::shared_ptr<FileInfos> infos)445 int32_t FileCopyManager::SendFileCore(std::shared_ptr<FDGuard> srcFdg,
446 std::shared_ptr<FDGuard> destFdg, std::shared_ptr<FileInfos> infos)
447 {
448 std::unique_ptr<uv_fs_t, decltype(fs_req_cleanup)*> sendFileReq = {
449 new (std::nothrow) uv_fs_t, fs_req_cleanup };
450 if (sendFileReq == nullptr) {
451 LOGE("Failed to request heap memory.");
452 return ENOMEM;
453 }
454 int64_t offset = 0;
455 struct stat srcStat{};
456 if (fstat(srcFdg->GetFD(), &srcStat) < 0) {
457 LOGE("Failed to get stat of file by fd: %{public}d ,errno = %{public}d", srcFdg->GetFD(), errno);
458 return errno;
459 }
460 int32_t ret = 0;
461 int64_t size = static_cast<int64_t>(srcStat.st_size);
462
463 while (size >= 0) {
464 ret = uv_fs_sendfile(nullptr, sendFileReq.get(), destFdg->GetFD(), srcFdg->GetFD(),
465 offset, MAX_SIZE, nullptr);
466 if (ret < 0) {
467 LOGE("Failed to sendfile by errno : %{public}d", errno);
468 return errno;
469 }
470
471 if (infos->needCancel.load()) {
472 LOGE("need cancel");
473 return FileManagement::E_DFS_CANCEL_SUCCESS; // 204
474 }
475
476 offset += static_cast<int64_t>(ret);
477 size -= static_cast<int64_t>(ret);
478 if (ret == 0) {
479 break;
480 }
481 }
482
483 if (size != 0) {
484 LOGE("The execution of the sendfile task was terminated, remaining file size %{public}" PRIu64, size);
485 return EIO;
486 }
487 return E_OK;
488 }
489
CopyDirFunc(const std::string & src,const std::string & dest,std::shared_ptr<FileInfos> infos)490 int32_t FileCopyManager::CopyDirFunc(const std::string &src, const std::string &dest, std::shared_ptr<FileInfos> infos)
491 {
492 LOGI("CopyDirFunc in");
493 size_t found = dest.find(src);
494 if (found != std::string::npos && found == 0) {
495 LOGE("not support copy src to dest");
496 return EINVAL;
497 }
498
499 // 获取src目录的目录名称
500 std::filesystem::path srcPath = std::filesystem::u8path(src);
501 std::string dirName;
502 if (srcPath.has_parent_path()) {
503 dirName = srcPath.parent_path().filename();
504 }
505
506 // 构造要拷贝到的路径
507 std::string destStr = dest + "/" + dirName;
508 return CopySubDir(src, destStr, infos);
509 }
510
CopySubDir(const std::string & srcPath,const std::string & destPath,std::shared_ptr<FileInfos> infos)511 int32_t FileCopyManager::CopySubDir(const std::string &srcPath,
512 const std::string &destPath, std::shared_ptr<FileInfos> infos)
513 {
514 std::error_code errCode;
515 if (!std::filesystem::exists(destPath, errCode) && errCode.value() == E_OK) {
516 int res = MakeDir(destPath);
517 if (res != E_OK) {
518 LOGE("Failed to mkdir");
519 return res;
520 }
521 } else if (errCode.value() != E_OK) {
522 LOGE("fs exists fail, errcode is %{public}d", errCode.value());
523 return errCode.value();
524 }
525 {
526 std::lock_guard<std::mutex> lock(infos->subDirsMutex);
527 infos->subDirs.insert(destPath);
528 }
529 return RecurCopyDir(srcPath, destPath, infos);
530 }
531
RecurCopyDir(const std::string & srcPath,const std::string & destPath,std::shared_ptr<FileInfos> infos)532 int32_t FileCopyManager::RecurCopyDir(const std::string &srcPath,
533 const std::string &destPath, std::shared_ptr<FileInfos> infos)
534 {
535 auto pNameList = FileSizeUtils::GetDirNameList(srcPath);
536 if (pNameList == nullptr) {
537 return ENOMEM;
538 }
539 for (int i = 0; i < pNameList->direntNum; i++) {
540 std::string src = srcPath + '/' + std::string((pNameList->namelist[i])->d_name);
541 std::string dest = destPath + '/' + std::string((pNameList->namelist[i])->d_name);
542 if ((pNameList->namelist[i])->d_type == DT_LNK) {
543 continue;
544 }
545 int ret = E_OK;
546 if ((pNameList->namelist[i])->d_type == DT_DIR) {
547 ret = CopySubDir(src, dest, infos);
548 } else {
549 ret = CopyFile(src, dest, infos);
550 }
551 if (ret != E_OK) {
552 return ret;
553 }
554 }
555 return E_OK;
556 }
557
AddFileInfos(std::shared_ptr<FileInfos> infos)558 void FileCopyManager::AddFileInfos(std::shared_ptr<FileInfos> infos)
559 {
560 std::lock_guard<std::mutex> lock(FileInfosVecMutex_);
561 FileInfosVec_.push_back(infos);
562 }
563
RemoveFileInfos(std::shared_ptr<FileInfos> infos)564 void FileCopyManager::RemoveFileInfos(std::shared_ptr<FileInfos> infos)
565 {
566 std::lock_guard<std::mutex> lock(FileInfosVecMutex_);
567 for (auto it = FileInfosVec_.begin(); it != FileInfosVec_.end();) {
568 if ((*it)->srcUri == infos->srcUri && (*it)->destUri == infos->destUri) {
569 it = FileInfosVec_.erase(it);
570 } else {
571 ++it;
572 }
573 }
574 }
575
CreateFileInfos(const std::string & srcUri,const std::string & destUri,std::shared_ptr<FileInfos> & infos)576 int32_t FileCopyManager::CreateFileInfos(const std::string &srcUri,
577 const std::string &destUri, std::shared_ptr<FileInfos> &infos)
578 {
579 infos->srcUri = srcUri;
580 infos->destUri = destUri;
581 infos->srcPath = FileSizeUtils::GetPathFromUri(srcUri, true);
582 infos->destPath = FileSizeUtils::GetPathFromUri(destUri, false);
583 infos->srcUriIsFile = IsMediaUri(infos->srcUri) || IsFile(infos->srcPath);
584 AddFileInfos(infos);
585 return E_OK;
586 }
587
GetModeFromFlags(unsigned int flags)588 std::string GetModeFromFlags(unsigned int flags)
589 {
590 const std::string readMode = "r";
591 const std::string writeMode = "w";
592 const std::string appendMode = "a";
593 const std::string truncMode = "t";
594 std::string mode = readMode;
595 mode += (((flags & O_RDWR) == O_RDWR) ? writeMode : "");
596 mode = (((flags & O_WRONLY) == O_WRONLY) ? writeMode : mode);
597 if (mode != readMode) {
598 mode += ((flags & O_TRUNC) ? truncMode : "");
599 mode += ((flags & O_APPEND) ? appendMode : "");
600 }
601 return mode;
602 }
603
OpenSrcFile(const std::string & srcPth,std::shared_ptr<FileInfos> infos,int32_t & srcFd)604 int32_t FileCopyManager::OpenSrcFile(const std::string &srcPth, std::shared_ptr<FileInfos> infos, int32_t &srcFd)
605 {
606 Uri uri(infos->srcUri);
607
608 if (uri.GetAuthority() == MEDIA) {
609 std::shared_ptr<DataShare::DataShareHelper> dataShareHelper = nullptr;
610 sptr<FileIoToken> remote = new (std::nothrow) IRemoteStub<FileIoToken>();
611 if (!remote) {
612 LOGE("Failed to get remote object");
613 return ENOMEM;
614 }
615 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
616 std::string userId;
617 if (GetAndCheckUserId(&uri, userId) && IsSystemApp()) {
618 dataShareHelper = DataShare::DataShareHelper::Creator(remote->AsObject(),
619 MEDIALIBRARY_DATA_URI + "?user=" + userId);
620 } else {
621 dataShareHelper = DataShare::DataShareHelper::Creator(remote->AsObject(), MEDIALIBRARY_DATA_URI);
622 }
623 #else
624 dataShareHelper = DataShare::DataShareHelper::Creator(remote->AsObject(), MEDIALIBRARY_DATA_URI);
625 #endif
626 if (!dataShareHelper) {
627 LOGE("Failed to connect to datashare");
628 return E_PERMISSION;
629 }
630 srcFd = dataShareHelper->OpenFile(uri, GetModeFromFlags(O_RDONLY));
631 if (srcFd < 0) {
632 LOGE("Open media uri by data share fail. ret = %{public}d", srcFd);
633 return EPERM;
634 }
635 } else {
636 srcFd = open(srcPth.c_str(), O_RDONLY);
637 if (srcFd < 0) {
638 LOGE("Error opening src file descriptor. errno = %{public}d", errno);
639 return errno;
640 }
641 if ((infos->needCancel.load()) && (srcPth.rfind(MTP_PATH_PREFIX, 0) != std::string::npos)) {
642 close(srcFd);
643 srcFd = -1;
644 LOGE("Source file copying is already canceled");
645 return FileManagement::E_DFS_CANCEL_SUCCESS;
646 }
647 }
648 return 0;
649 }
650
MakeDir(const std::string & path)651 int FileCopyManager::MakeDir(const std::string &path)
652 {
653 std::filesystem::path destDir(path);
654 std::error_code errCode;
655 if (!std::filesystem::create_directory(destDir, errCode)) {
656 LOGE("Failed to create directory, error code: %{public}d", errCode.value());
657 return errCode.value();
658 }
659 return E_OK;
660 }
661
IsRemoteUri(const std::string & uri)662 bool FileCopyManager::IsRemoteUri(const std::string &uri)
663 {
664 // NETWORK_PARA
665 return uri.find(NETWORK_PARA) != uri.npos;
666 }
667
IsMediaUri(const std::string & uriPath)668 bool FileCopyManager::IsMediaUri(const std::string &uriPath)
669 {
670 Uri uri(uriPath);
671 std::string bundleName = uri.GetAuthority();
672 return bundleName == MEDIA;
673 }
674
CheckOrCreatePath(const std::string & destPath)675 int32_t FileCopyManager::CheckOrCreatePath(const std::string &destPath)
676 {
677 std::error_code errCode;
678 if (!std::filesystem::exists(destPath, errCode) && errCode.value() == E_OK) {
679 LOGI("destPath not exist");
680 auto file = open(destPath.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
681 if (file < 0) {
682 LOGE("Error opening file descriptor. errno = %{public}d", errno);
683 return errno;
684 }
685 close(file);
686 } else if (errCode.value() != 0) {
687 return errCode.value();
688 }
689 return E_OK;
690 }
691 } // namespace DistributedFile
692 } // namespace Storage
693 } // namespace OHOS
694