• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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