• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "remote_file_share.h"
17 
18 #include <climits>
19 #include <fcntl.h>
20 #include <pthread.h>
21 #include <sys/ioctl.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25 
26 #include "log.h"
27 #ifdef ENABLE_DEVICE_MANAGER
28 #include "device_manager.h"
29 #include "device_manager_callback.h"
30 #endif
31 #include "iservice_registry.h"
32 #include "istorage_manager.h"
33 #include "sandbox_helper.h"
34 #include "securec.h"
35 #include "system_ability_definition.h"
36 #include "unique_fd.h"
37 #include "uri.h"
38 
39 namespace OHOS {
40 namespace AppFileService {
41 namespace ModuleRemoteFileShare {
42 #ifdef ENABLE_DEVICE_MANAGER
43 using namespace OHOS::DistributedHardware;
44 #endif
45 namespace {
46 const int E_OK = 0;
47 const int HMDFS_CID_SIZE = 64;
48 const int USER_ID_INIT = 100;
49 const unsigned HMDFS_IOC = 0xf2;
50 const std::string FILE_SCHEME = "file";
51 const std::string BACKSLASH = "/";
52 const std::string DISTRIBUTED_DIR_PATH = "/data/storage/el2/distributedfiles";
53 const std::string DST_PATH_HEAD = "/data/service/el2/";
54 const std::string DST_PATH_MID = "/hmdfs/account/data/";
55 const std::string DST_PATH_MID_FILES = "/hmdfs/account/files/";
56 const std::string SHARE_PATH_HEAD = "/mnt/hmdfs/";
57 const std::string SHARE_PATH_MID = "/account/merge_view/services/";
58 const std::string LOWER_SHARE_PATH_HEAD = "/mnt/hmdfs/";
59 const std::string LOWER_SHARE_PATH_MID = "/account/device_view/local/services/";
60 const std::string SHARE_PATH_DIR = "/.share";
61 const std::string REMOTE_SHARE_PATH_DIR = "/.remote_share";
62 const std::string MEDIA_AUTHORITY = "media";
63 const std::string FILE_MANAGER_AUTHORITY = "docs";
64 const std::string PACKAGE_NAME = "get_dfs_uri_from_local";
65 const std::string NETWORK_PARA = "?networkid=";
66 const std::string MEDIA_BUNDLE_NAME = "com.ohos.medialibrary.medialibrarydata";
67 const std::string FILE_MANAGER_URI_HEAD = "/storage/";
68 const std::string REMOTE_SHARE_PATH_MID = "hmdfs/";
69 const std::string SANDBOX_BASE_DIR = "/data/storage/el2/base";
70 const std::string SANDBOX_CLOUD_DIR = "/data/storage/el2/cloud";
71 const std::string MEDIA_PHOTO_PATH = "/Photo";
72 const std::string MEDIA_PATH_PREFIX_ONE = "/account/cloud_merge_view/files";
73 const std::string MEDIA_PATH_PREFIX_TWO = "/account/merge_view/files";
74 constexpr int32_t GET_CLIENT_RETRY_TIMES = 5;
75 constexpr int32_t SLEEP_TIME = 1;
76 } //namespace
77 
78 #define HMDFS_IOC_SET_SHARE_PATH _IOW(HMDFS_IOC, 1, struct HmdfsShareControl)
79 #define HMDFS_IOC_GET_DST_PATH _IOR(HMDFS_IOC, 3, unsigned int)
80 
81 struct HmdfsShareControl {
82     int fd;
83     char deviceId[HMDFS_CID_SIZE];
84 };
85 
86 struct HmdfsDstInfo {
87     uint64_t localLen;
88     uint64_t localPathIndex;
89     uint64_t distributedLen;
90     uint64_t distributedPathIndex;
91     uint64_t bundleNameLen;
92     uint64_t bundleNameIndex;
93     uint64_t size;
94 };
95 
96 #ifdef ENABLE_DEVICE_MANAGER
97 class InitDMCallback : public DmInitCallback {
98 public:
99     InitDMCallback() = default;
100     ~InitDMCallback() override = default;
OnRemoteDied()101     void OnRemoteDied() override {};
102 };
103 #endif
104 
GetProcessName()105 static std::string GetProcessName()
106 {
107     char pthreadName[PATH_MAX];
108     int ret = pthread_getname_np(pthread_self(), pthreadName, sizeof(pthreadName));
109     if (ret != E_OK) {
110         LOGE("RemoteFileShare::GetProcessName, pthread_getname_np failed with %{public}d", errno);
111         return "";
112     }
113     std::string pthreadNameStr = pthreadName;
114     LOGI("RemoteFileShare::GetProcessName, thread name is %{public}s", pthreadNameStr.c_str());
115     return pthreadNameStr;
116 }
117 
GetFileName(const int & fd)118 static std::string GetFileName(const int &fd)
119 {
120     char buf[PATH_MAX] = {'\0'};
121     char filePath[PATH_MAX] = {'\0'};
122 
123     int ret = snprintf_s(buf, sizeof(buf), sizeof(buf), "/proc/self/fd/%d", fd);
124     if (ret < 0) {
125         LOGE("RemoteFileShare::GetFileName, snprintf failed with %{public}d", errno);
126         return "";
127     }
128 
129     ret = readlink(buf, filePath, PATH_MAX);
130     if (ret < 0 || ret >= PATH_MAX) {
131         LOGE("RemoteFileShare::GetFileName, readlink failed with %{public}d", errno);
132         return "";
133     }
134 
135     std::string fileName = filePath;
136     std::size_t firstSlash = fileName.rfind("/");
137     if (firstSlash == fileName.npos) {
138         LOGE("RemoteFileShare::GetFileName, get error path");
139         return "";
140     }
141     fileName = fileName.substr(firstSlash + 1, fileName.size() - firstSlash);
142     return fileName;
143 }
144 
CreateShareDir(const std::string & path)145 static int CreateShareDir(const std::string &path)
146 {
147     if (access(path.c_str(), F_OK) != 0) {
148         int ret = mkdir(path.c_str(), S_IRWXU);
149         if (ret != E_OK) {
150             LOGE("RemoteFileShare::CreateShareDir, make dir failed with %{public}d", errno);
151             return errno;
152         }
153     }
154     return E_OK;
155 }
156 
GetSharePath(const int & userId,const std::string & packageName)157 static std::string GetSharePath(const int &userId, const std::string &packageName)
158 {
159     return SHARE_PATH_HEAD + std::to_string(userId) + SHARE_PATH_MID + packageName;
160 }
161 
GetLowerSharePath(const int & userId,const std::string & packageName)162 static std::string GetLowerSharePath(const int &userId, const std::string &packageName)
163 {
164     return LOWER_SHARE_PATH_HEAD + std::to_string(userId) + LOWER_SHARE_PATH_MID + packageName;
165 }
166 
DeleteShareDir(const std::string & PACKAGE_PATH,const std::string & SHARE_PATH)167 static bool DeleteShareDir(const std::string &PACKAGE_PATH, const std::string &SHARE_PATH)
168 {
169     bool result = true;
170     if (access(SHARE_PATH.c_str(), F_OK) == E_OK) {
171         int ret = rmdir(SHARE_PATH.c_str());
172         if (ret != E_OK) {
173             LOGE("RemoteFileShare::DeleteShareDir, delete dir failed with %{public}d", errno);
174             result = false;
175         } else {
176             LOGI("RemoteFileShare::DeleteShareDir, delete path successfully");
177         }
178     }
179     if (access(PACKAGE_PATH.c_str(), F_OK) == E_OK) {
180         int ret = rmdir(PACKAGE_PATH.c_str());
181         if (ret != E_OK) {
182             LOGE("RemoteFileShare::DeleteShareDir, delete dir failed with %{public}d", errno);
183             result = false;
184         } else {
185             LOGI("RemoteFileShare::DeleteShareDir, delete path successfully");
186         }
187     }
188     return result;
189 }
190 
CreateShareFile(struct HmdfsShareControl & shareControl,const char * file,const std::string & deviceId)191 static int CreateShareFile(struct HmdfsShareControl &shareControl, const char *file, const std::string &deviceId)
192 {
193     int32_t dirFd = open(file, O_RDONLY);
194     if (dirFd < 0) {
195         LOGE("RemoteFileShare::CreateShareFile, open share path failed with %{public}d", errno);
196         return errno;
197     }
198 
199     memset_s(shareControl.deviceId, HMDFS_CID_SIZE, '\0', HMDFS_CID_SIZE);
200     if (memcpy_s(shareControl.deviceId, HMDFS_CID_SIZE, deviceId.c_str(), deviceId.size()) != 0) {
201         LOGE("RemoteFileShare::CreateShareFile, memcpy_s failed with %{public}d", errno);
202         close(dirFd);
203         return errno;
204     }
205 
206     if (ioctl(dirFd, HMDFS_IOC_SET_SHARE_PATH, &shareControl) < 0) {
207         LOGE("RemoteFileShare::CreateShareFile, ioctl failed with %{public}d", errno);
208     }
209     close(dirFd);
210     return E_OK;
211 }
212 
CheckInputValidity(const int & fd,const int & userId,const std::string & deviceId)213 static int CheckInputValidity(const int &fd, const int &userId, const std::string &deviceId)
214 {
215     return (fd < 0) || (userId < USER_ID_INIT) || (deviceId != SHARE_ALL_DEVICE && deviceId.size() != HMDFS_CID_SIZE);
216 }
217 
CreateSharePath(const int & fd,std::string & sharePath,const int & userId,const std::string & deviceId)218 int RemoteFileShare::CreateSharePath(const int &fd,
219                                      std::string &sharePath,
220                                      const int &userId,
221                                      const std::string &deviceId)
222 {
223     struct HmdfsShareControl shareControl;
224     shareControl.fd = fd;
225 
226     if (CheckInputValidity(fd, userId, deviceId) != E_OK) {
227         LOGE("RemoteFileShare::CreateSharePath, invalid argument with %{public}d", EINVAL);
228         return EINVAL;
229     }
230 
231     const std::string processName = GetProcessName();
232     if (processName == "") {
233         LOGE("RemoteFileShare::CreateSharePath, GetProcessName failed with %{public}d", errno);
234         return errno;
235     }
236 
237     const std::string PACKAGE_PATH = GetLowerSharePath(userId, processName);
238     if (!SandboxHelper::IsValidPath(PACKAGE_PATH)) {
239         LOGE("RemoteFileShare::CreateSharePath, GetLowerSharePath failed");
240         return EACCES;
241     }
242 
243     const std::string LOWER_SHARE_PATH = PACKAGE_PATH + SHARE_PATH_DIR;
244     if (CreateShareDir(PACKAGE_PATH) != E_OK)
245         return errno;
246     if (CreateShareDir(LOWER_SHARE_PATH) != E_OK) {
247         DeleteShareDir(PACKAGE_PATH, LOWER_SHARE_PATH);
248         return errno;
249     }
250 
251     const std::string SHARE_PATH = GetSharePath(userId, processName) + SHARE_PATH_DIR;
252     char realPath[PATH_MAX] = {'\0'};
253     if (!realpath(SHARE_PATH.c_str(), realPath)) {
254         LOGE("RemoteFileShare::CreateSharePath, realpath failed with %{public}d", errno);
255         DeleteShareDir(PACKAGE_PATH, LOWER_SHARE_PATH);
256         return errno;
257     }
258 
259     std::string file_name = GetFileName(shareControl.fd);
260     if (file_name == "") {
261         LOGE("RemoteFileShare::CreateSharePath, get error file name");
262         DeleteShareDir(PACKAGE_PATH, LOWER_SHARE_PATH);
263         return EBADF;
264     }
265     sharePath = SHARE_PATH + "/" + file_name;
266 
267     if (CreateShareFile(shareControl, realPath, deviceId) != E_OK) {
268         LOGE("RemoteFileShare::CreateSharePath, create share file failed with %{public}d", errno);
269         /* When the file is exist, we should not delete the dictionary */
270         if (errno == EEXIST) {
271             return E_OK;
272         }
273         sharePath = "";
274         DeleteShareDir(PACKAGE_PATH, LOWER_SHARE_PATH);
275         return errno;
276     }
277     LOGI("RemoteFileShare::CreateSharePath, create successfully");
278     return E_OK;
279 }
280 
GetDistributedPath(Uri & uri,const int & userId,std::string & distributedPath,const std::string & bundleName,const std::string & networkId)281 static int GetDistributedPath(Uri &uri,
282                               const int &userId,
283                               std::string &distributedPath,
284                               const std::string &bundleName,
285                               const std::string &networkId)
286 {
287     distributedPath = DST_PATH_HEAD + std::to_string(userId) + DST_PATH_MID + bundleName + REMOTE_SHARE_PATH_DIR +
288                       BACKSLASH + networkId + SandboxHelper::Decode(uri.GetPath());
289     if (distributedPath.size() >= PATH_MAX) {
290         LOGE("Path is too long with %{public}zu", distributedPath.size());
291         return -EINVAL;
292     }
293 
294     return E_OK;
295 }
296 
GetMediaDistributedDir(const int & userId,std::string & distributedDir,const std::string & networkId)297 static int GetMediaDistributedDir(const int &userId, std::string &distributedDir, const std::string &networkId)
298 {
299     distributedDir = DST_PATH_HEAD + std::to_string(userId) + DST_PATH_MID + MEDIA_BUNDLE_NAME +
300         REMOTE_SHARE_PATH_DIR + BACKSLASH + networkId + MEDIA_PHOTO_PATH;
301     if (distributedDir.size() >= PATH_MAX) {
302         LOGE("Path is too long with %{public}zu", distributedDir.size());
303         return -EINVAL;
304     }
305     LOGI("media distributedDir: %{private}s", distributedDir.c_str());
306     return E_OK;
307 }
308 
GetSandboxDir(Uri uri)309 static std::string GetSandboxDir(Uri uri)
310 {
311     std::string sandboxPath = SandboxHelper::Decode(uri.GetPath());
312     std::string sandboxDir = "";
313     if (sandboxPath.rfind(DISTRIBUTED_DIR_PATH, 0) == 0) {
314         sandboxDir = DISTRIBUTED_DIR_PATH;
315     } else if (sandboxPath.rfind(SANDBOX_BASE_DIR, 0) == 0) {
316         sandboxDir = SANDBOX_BASE_DIR;
317     } else if (sandboxPath.rfind(SANDBOX_CLOUD_DIR, 0) == 0) {
318         sandboxDir = SANDBOX_CLOUD_DIR;
319     } else {
320         LOGE("Get distributed dir failed.");
321         return "";
322     }
323     return sandboxDir;
324 }
325 
IsDistributedFileDir(Uri uri)326 static bool IsDistributedFileDir(Uri uri)
327 {
328     std::string sandboxDir = GetSandboxDir(uri);
329     return sandboxDir == DISTRIBUTED_DIR_PATH ? true : false;
330 }
331 
IsCloudFileDir(Uri uri)332 static bool IsCloudFileDir(Uri uri)
333 {
334     std::string sandboxDir = GetSandboxDir(uri);
335     return sandboxDir == SANDBOX_CLOUD_DIR ? true : false;
336 }
337 
GetDistributedDir(const int & userId,std::string & distributedDir,const std::string & bundleName,const std::string & networkId,Uri uri)338 static int GetDistributedDir(const int &userId, std::string &distributedDir, const std::string &bundleName,
339     const std::string &networkId, Uri uri)
340 {
341     std::string sandboxDir = GetSandboxDir(uri);
342     if (sandboxDir == "") {
343         LOGE("Get sandbox dir failed");
344         return -EINVAL;
345     }
346 
347     distributedDir = DST_PATH_HEAD + std::to_string(userId) + DST_PATH_MID + bundleName + REMOTE_SHARE_PATH_DIR +
348         BACKSLASH + networkId + sandboxDir;
349     if (distributedDir.size() >= PATH_MAX) {
350         LOGE("Path is too long with %{public}zu", distributedDir.size());
351         return -EINVAL;
352     }
353     LOGI("bundleName: %{public}s, distributedDir: %{private}s", bundleName.c_str(), distributedDir.c_str());
354     return E_OK;
355 }
356 
GetMediaPhysicalDir(const int32_t & userId,std::string & physicalDir,const std::string & bundleName)357 static int32_t GetMediaPhysicalDir(const int32_t &userId, std::string &physicalDir, const std::string &bundleName)
358 {
359     if (bundleName != MEDIA_BUNDLE_NAME) {
360         LOGE("bundleName is not media type.");
361         return -EINVAL;
362     }
363     physicalDir = DST_PATH_HEAD + std::to_string(userId) + DST_PATH_MID_FILES + MEDIA_PHOTO_PATH;
364     if (physicalDir.size() >= PATH_MAX) {
365         LOGE("Path is too long with %{public}zu", physicalDir.size());
366         return -EINVAL;
367     }
368     LOGI("bundleName: %{public}s, physicalDir: %{private}s", bundleName.c_str(), physicalDir.c_str());
369     return E_OK;
370 }
371 
GetPhysicalDir(Uri & uri,const int32_t & userId)372 static std::string GetPhysicalDir(Uri &uri, const int32_t &userId)
373 {
374     std::string sandboxPath = SandboxHelper::Decode(uri.GetPath());
375     if (!SandboxHelper::IsValidPath(sandboxPath) || uri.GetScheme() != FILE_SCHEME) {
376         LOGE("Sandbox path from uri is error");
377         return "";
378     }
379 
380     std::string physicalDir = "";
381     int ret = SandboxHelper::GetPhysicalDir(uri.ToString(), std::to_string(userId), physicalDir);
382     if (ret != E_OK) {
383         LOGE("Get physical path failed with %{public}d", ret);
384         return "";
385     }
386     return physicalDir;
387 }
388 
GetPhysicalPath(Uri & uri,const std::string & userId)389 static std::string GetPhysicalPath(Uri &uri, const std::string &userId)
390 {
391     std::string sandboxPath = SandboxHelper::Decode(uri.GetPath());
392     if (!SandboxHelper::IsValidPath(sandboxPath) || uri.GetScheme() != FILE_SCHEME) {
393         LOGE("Sandbox path from uri is error");
394         return "";
395     }
396 
397     std::string physicalPath = "";
398     int ret = SandboxHelper::GetPhysicalPath(uri.ToString(), userId, physicalPath);
399     if (ret != E_OK) {
400         LOGE("Get physical path failed with %{public}d", ret);
401         return "";
402     }
403     return physicalPath;
404 }
405 
InitHmdfsInfo(struct HmdfsDstInfo & hdi,const std::string & physicalPath,const std::string & distributedPath,const std::string & bundleName)406 static void InitHmdfsInfo(struct HmdfsDstInfo &hdi,
407                           const std::string &physicalPath,
408                           const std::string &distributedPath,
409                           const std::string &bundleName)
410 {
411     hdi.localLen = physicalPath.size() + 1;
412     hdi.localPathIndex = reinterpret_cast<uint64_t>(physicalPath.c_str());
413 
414     hdi.distributedLen = distributedPath.size() + 1;
415     hdi.distributedPathIndex = reinterpret_cast<uint64_t>(distributedPath.c_str());
416 
417     hdi.bundleNameLen = bundleName.size() + 1;
418     hdi.bundleNameIndex = reinterpret_cast<uint64_t>(bundleName.c_str());
419 
420     hdi.size = reinterpret_cast<uint64_t>(&hdi.size);
421 }
422 
GetLocalNetworkId()423 static std::string GetLocalNetworkId()
424 {
425     const std::string LOCAL = "local";
426     std::string networkId = LOCAL;
427 #ifdef ENABLE_DEVICE_MANAGER
428     auto callback = std::make_shared<InitDMCallback>();
429     int32_t ret = DeviceManager::GetInstance().InitDeviceManager(PACKAGE_NAME, callback);
430     if (ret != 0) {
431         return "";
432     }
433 
434     DmDeviceInfo info;
435     ret = DeviceManager::GetInstance().GetLocalDeviceInfo(PACKAGE_NAME, info);
436     networkId = std::string(info.networkId);
437     LOGD("GetLocalNetworkId :%{private}s", networkId.c_str());
438     if (ret != 0 || networkId.empty()) {
439         return "";
440     }
441 #endif
442     return networkId;
443 }
444 
SetHmdfsUriInfo(struct HmdfsUriInfo & hui,Uri & uri,uint64_t fileSize,const std::string & networkId,const std::string & bundleName)445 static void SetHmdfsUriInfo(struct HmdfsUriInfo &hui,
446                             Uri &uri,
447                             uint64_t fileSize,
448                             const std::string &networkId,
449                             const std::string &bundleName)
450 {
451     hui.uriStr = FILE_SCHEME + "://" + bundleName + DISTRIBUTED_DIR_PATH + REMOTE_SHARE_PATH_DIR + BACKSLASH +
452                  networkId + uri.GetPath() + NETWORK_PARA + networkId;
453 
454     hui.fileSize = fileSize;
455     return;
456 }
457 
SetFileSize(const std::string & physicalPath,struct HmdfsUriInfo & hui)458 static int32_t SetFileSize(const std::string &physicalPath, struct HmdfsUriInfo &hui)
459 {
460     struct stat buf = {};
461     if (stat(physicalPath.c_str(), &buf) != E_OK) {
462         int32_t ret = -errno;
463         LOGE("Failed to get physical path stat with %{public}d", ret);
464         return ret;
465     }
466     hui.fileSize = static_cast<size_t>(buf.st_size);
467     return E_OK;
468 }
469 
SetPublicDirHmdfsInfo(const std::string & physicalPath,const std::string & uriStr,struct HmdfsUriInfo & hui,const std::string & networkId)470 static int32_t SetPublicDirHmdfsInfo(const std::string &physicalPath, const std::string &uriStr,
471                                      struct HmdfsUriInfo &hui, const std::string &networkId)
472 {
473     hui.uriStr = uriStr + NETWORK_PARA + networkId;
474     struct stat buf = {};
475     if (stat(physicalPath.c_str(), &buf) != E_OK) {
476         LOGE("Failed to get physical path stat with %{public}d", -errno);
477         return -errno;
478     }
479     hui.fileSize = static_cast<size_t>(buf.st_size);
480     return E_OK;
481 }
482 
GetMergePathFd(HmdfsDstInfo & hdi,UniqueFd & dirFd,const int32_t & userId)483 static int32_t GetMergePathFd(HmdfsDstInfo &hdi, UniqueFd &dirFd, const int32_t &userId)
484 {
485     LOGI("Open merge path start");
486     std::string ioctlDir = SHARE_PATH_HEAD + std::to_string(userId) + SHARE_PATH_MID;
487     UniqueFd dirMergeFd(open(ioctlDir.c_str(), O_RDONLY));
488     if (dirFd < 0) {
489         LOGE("Open merge path failed with %{public}d", errno);
490         return errno;
491     }
492     int32_t ret = ioctl(dirMergeFd, HMDFS_IOC_GET_DST_PATH, &hdi);
493     if (ret != E_OK) {
494         LOGE("Ioctl merge failed with %{public}d", errno);
495         return -errno;
496     }
497     dirFd = std::move(dirMergeFd);
498     return E_OK;
499 }
500 
GetDfsUriFromLocal(const std::string & uriStr,const int32_t & userId,struct HmdfsUriInfo & hui)501 int32_t RemoteFileShare::GetDfsUriFromLocal(const std::string &uriStr, const int32_t &userId, struct HmdfsUriInfo &hui)
502 {
503     LOGI("GetDfsUriFromLocal start");
504     Uri uri(uriStr);
505     std::string bundleName = uri.GetAuthority();
506     std::string physicalPath = GetPhysicalPath(uri, std::to_string(userId));
507     if (physicalPath == "") {
508         LOGE("Failed to get physical path");
509         return -EINVAL;
510     }
511     if (bundleName == MEDIA_AUTHORITY) {
512         bundleName = MEDIA_BUNDLE_NAME;
513     }
514 
515     std::string networkId = GetLocalNetworkId();
516     if (bundleName == FILE_MANAGER_AUTHORITY) {
517         (void)SetPublicDirHmdfsInfo(physicalPath, uriStr, hui, networkId);
518         LOGD("GetDfsUriFromLocal successfully");
519         return E_OK;
520     }
521 
522     std::string distributedPath;
523     int ret = GetDistributedPath(uri, userId, distributedPath, bundleName, networkId);
524     if (ret != E_OK) {
525         return ret;
526     }
527 
528     struct HmdfsDstInfo hdi;
529     InitHmdfsInfo(hdi, physicalPath, distributedPath, bundleName);
530     LOGI("open ioctlDir Create ioctl start");
531     std::string ioctlDir = SHARE_PATH_HEAD + std::to_string(userId) + LOWER_SHARE_PATH_MID;
532     UniqueFd dirFd(open(ioctlDir.c_str(), O_RDONLY));
533     if (dirFd < 0) {
534         LOGE("Open share path failed with %{public}d", errno);
535         return errno;
536     }
537 
538     ret = ioctl(dirFd, HMDFS_IOC_GET_DST_PATH, &hdi);
539     if (ret != E_OK && GetMergePathFd(hdi, dirFd, userId) != E_OK) {
540         return errno;
541     }
542     SetHmdfsUriInfo(hui, uri, hdi.size, networkId, bundleName);
543     LOGI("GetDfsUriFromLocal successfully");
544     return E_OK;
545 }
546 
UriCategoryByType(const std::vector<std::string> & uriList,std::vector<std::string> & mediaUriList,std::vector<std::string> & otherUriList)547 static int32_t UriCategoryByType(const std::vector<std::string> &uriList,
548                                  std::vector<std::string> &mediaUriList,
549                                  std::vector<std::string> &otherUriList)
550 {
551     LOGI("GetDfsUrisFromLocal UriCategoryByType start");
552     if (uriList.size() == 0) {
553         LOGE("Parameter uriList is NULL");
554         return -EINVAL;
555     }
556     for (auto &uriStr : uriList) {
557         Uri uri(uriStr);
558         std::string bundleName = uri.GetAuthority();
559         if (bundleName == MEDIA_AUTHORITY) {
560             mediaUriList.push_back(uriStr);
561         } else {
562             otherUriList.push_back(uriStr);
563         }
564     }
565     return E_OK;
566 }
567 
GetMediaDfsUrisFromLocal(const std::vector<std::string> & uriList,const int32_t & userId,std::unordered_map<std::string,HmdfsUriInfo> & uriToDfsUriMaps)568 static int32_t GetMediaDfsUrisFromLocal(const std::vector<std::string> &uriList,
569                                         const int32_t &userId,
570                                         std::unordered_map<std::string, HmdfsUriInfo> &uriToDfsUriMaps)
571 {
572     LOGI("GetMediaDfsUrisFromLocal start");
573     std::string ioctlDir = SHARE_PATH_HEAD + std::to_string(userId) + LOWER_SHARE_PATH_MID;
574     UniqueFd dirFd(open(ioctlDir.c_str(), O_RDONLY));
575     if (dirFd < 0) {
576         LOGE("Open share path failed with %{public}d", errno);
577         return errno;
578     }
579     std::vector<std::string> physicalPaths;
580     int getPhysicalPathRet = SandboxHelper::GetMediaSharePath(uriList, physicalPaths);
581     if (getPhysicalPathRet != E_OK) {
582         return -EINVAL;
583     }
584     std::string networkId = GetLocalNetworkId();
585     std::string bundleName = MEDIA_BUNDLE_NAME;
586     for (size_t i = 0; i < uriList.size(); i++) {
587         Uri uri(uriList[i]);
588         LOGD("GetDfsUriFromLocal begin, uri: %{private}s", uriList[i].c_str());
589         std::string distributedPath;
590         int ret = GetDistributedPath(uri, userId, distributedPath, bundleName, networkId);
591         if (ret != E_OK) {
592             return ret;
593         }
594         struct HmdfsDstInfo hdi;
595         InitHmdfsInfo(hdi, physicalPaths[i], distributedPath, bundleName);
596         ret = ioctl(dirFd, HMDFS_IOC_GET_DST_PATH, &hdi);
597         if (ret != E_OK && GetMergePathFd(hdi, dirFd, userId) != E_OK) {
598             return errno;
599         }
600         HmdfsUriInfo dfsUriInfo;
601         SetHmdfsUriInfo(dfsUriInfo, uri, hdi.size, networkId, bundleName);
602         uriToDfsUriMaps.insert({uriList[i], dfsUriInfo});
603     }
604     LOGI("GetDfsUrisFromLocal successfully");
605     return E_OK;
606 }
607 
GetDfsUrisFromLocal(const std::vector<std::string> & uriList,const int32_t & userId,std::unordered_map<std::string,HmdfsUriInfo> & uriToDfsUriMaps)608 int32_t RemoteFileShare::GetDfsUrisFromLocal(const std::vector<std::string> &uriList,
609                                              const int32_t &userId,
610                                              std::unordered_map<std::string, HmdfsUriInfo> &uriToDfsUriMaps)
611 {
612     std::vector<std::string> otherUriList;
613     std::vector<std::string> mediaUriList;
614     int ret = UriCategoryByType(uriList, mediaUriList, otherUriList);
615     if (ret == E_OK && mediaUriList.size() != E_OK) {
616         ret = GetMediaDfsUrisFromLocal(mediaUriList, userId, uriToDfsUriMaps);
617     }
618     if (ret != E_OK) {
619         return ret;
620     }
621     std::string ioctlDir = SHARE_PATH_HEAD + std::to_string(userId) + LOWER_SHARE_PATH_MID;
622     UniqueFd dirFd(open(ioctlDir.c_str(), O_RDONLY));
623     if (dirFd < 0) {
624         LOGE("Open share path failed with %{public}d", errno);
625         return errno;
626     }
627     std::string networkId = GetLocalNetworkId();
628     for (const auto &uriStr : otherUriList) {
629         Uri uri(uriStr);
630         std::string bundleName = uri.GetAuthority();
631         LOGD("GetDfsUriFromLocal begin, uri: %{private}s", uriStr.c_str());
632         std::string physicalPath = GetPhysicalPath(uri, std::to_string(userId));
633         if (physicalPath == "") {
634             LOGE("Failed to get physical path");
635             return -EINVAL;
636         }
637         if (bundleName == FILE_MANAGER_AUTHORITY) {
638             HmdfsUriInfo dfsUriInfo;
639             (void)SetPublicDirHmdfsInfo(physicalPath, uriStr, dfsUriInfo, networkId);
640             uriToDfsUriMaps.insert({uriStr, dfsUriInfo});
641             continue;
642         }
643 
644         std::string distributedPath;
645         ret = GetDistributedPath(uri, userId, distributedPath, bundleName, networkId);
646         if (ret != E_OK) {
647             return ret;
648         }
649         struct HmdfsDstInfo hdi;
650         InitHmdfsInfo(hdi, physicalPath, distributedPath, bundleName);
651         ret = ioctl(dirFd, HMDFS_IOC_GET_DST_PATH, &hdi);
652         if (ret != E_OK && GetMergePathFd(hdi, dirFd, userId) != E_OK) {
653             return errno;
654         }
655         HmdfsUriInfo dfsUriInfo;
656         SetHmdfsUriInfo(dfsUriInfo, uri, hdi.size, networkId, bundleName);
657         uriToDfsUriMaps.insert({uriStr, dfsUriInfo});
658     }
659     LOGI("GetDfsUrisFromLocal successfully");
660     return E_OK;
661 }
662 
GetStorageManager()663 static sptr<StorageManager::IStorageManager> GetStorageManager()
664 {
665     auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
666     if (saMgr == nullptr) {
667         LOGI("Get samgr failed.");
668         return nullptr;
669     }
670 
671     int32_t count = 0;
672     sptr<StorageManager::IStorageManager> storageManager = nullptr;
673     while (storageManager == nullptr && count < GET_CLIENT_RETRY_TIMES) {
674         count++;
675         auto storageObj = saMgr->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID);
676         if (storageObj == nullptr) {
677             LOGE("Get starage manger failed.");
678             sleep(SLEEP_TIME);
679             continue;
680         }
681 
682         storageManager = iface_cast<StorageManager::IStorageManager>(storageObj);
683         if (storageManager == nullptr) {
684             LOGE("Iface_cast failed.");
685             sleep(SLEEP_TIME);
686             continue;
687         }
688     }
689     return storageManager;
690 }
691 
MountDisFileShare(const int32_t & userId,const std::string & distributedDir,const std::string & physicalDir)692 static int32_t MountDisFileShare(const int32_t &userId, const std::string &distributedDir,
693     const std::string &physicalDir)
694 {
695     if (distributedDir == "" || physicalDir == "") {
696         LOGE("Invalid distributedDir or physicalDir.");
697         return -EINVAL;
698     }
699     auto storageMgr = GetStorageManager();
700     if (storageMgr == nullptr) {
701         LOGE("Get storage manager failed.");
702         return -EINVAL;
703     }
704 
705     std::map<std::string, std::string> shareFiles = {
706         {distributedDir, physicalDir}
707     };
708     int32_t ret = storageMgr->MountDisShareFile(userId, shareFiles);
709     if (ret != E_OK) {
710         LOGE("MountDisShareFile failed.");
711         return ret;
712     }
713     return E_OK;
714 }
715 
GetMediaSandboxPath(const std::string & physicalPath,const std::string & usrId)716 static std::string GetMediaSandboxPath(const std::string &physicalPath, const std::string &usrId)
717 {
718     const std::vector<std::string> prefixList = {
719         SHARE_PATH_HEAD + usrId + MEDIA_PATH_PREFIX_ONE,
720         SHARE_PATH_HEAD + usrId + MEDIA_PATH_PREFIX_TWO
721     };
722     std::string mediaSandboxPath = "";
723     for (size_t i = 0; i < prefixList.size(); i++) {
724         std::string sandboxPathPrefix = prefixList[i];
725         std::string::size_type prefixMatchLen = sandboxPathPrefix.length();
726         if (physicalPath.length() >= prefixMatchLen) {
727             std::string sandboxPathTemp = physicalPath.substr(0, prefixMatchLen);
728             if (sandboxPathTemp == sandboxPathPrefix) {
729                 mediaSandboxPath = physicalPath.substr(prefixMatchLen);
730                 LOGI("mediaSandboxPath: %{private}s", mediaSandboxPath.c_str());
731                 return mediaSandboxPath;
732             }
733         }
734     }
735     return mediaSandboxPath;
736 }
737 
SetHmdfsUriDirInfo(struct HmdfsUriInfo & hui,Uri & uri,const std::string & physicalPath,const std::string & networkId,const std::string & bundleName)738 static int32_t SetHmdfsUriDirInfo(struct HmdfsUriInfo &hui, Uri &uri, const std::string &physicalPath,
739     const std::string &networkId, const std::string &bundleName)
740 {
741     hui.uriStr = FILE_SCHEME + "://" + bundleName + DISTRIBUTED_DIR_PATH + REMOTE_SHARE_PATH_DIR + BACKSLASH +
742         networkId + uri.GetPath() + NETWORK_PARA + networkId;
743     return SetFileSize(physicalPath, hui);
744 }
745 
SetDistributedfilesHmdfsUriDirInfo(const std::string & physicalPath,const std::string & uriStr,struct HmdfsUriInfo & hui,const std::string & networkId)746 static int32_t SetDistributedfilesHmdfsUriDirInfo(const std::string &physicalPath, const std::string &uriStr,
747     struct HmdfsUriInfo &hui, const std::string &networkId)
748 {
749     hui.uriStr = uriStr + NETWORK_PARA + networkId;
750     return SetFileSize(physicalPath, hui);
751 }
752 
SetMediaHmdfsUriDirInfo(struct HmdfsUriInfo & hui,Uri & uri,const std::string & physicalPath,const std::string & networkId,const std::string & usrId)753 static int32_t SetMediaHmdfsUriDirInfo(struct HmdfsUriInfo &hui, Uri &uri, const std::string &physicalPath,
754     const std::string &networkId, const std::string &usrId)
755 {
756     std::string authority = uri.GetAuthority();
757     if (authority != MEDIA_AUTHORITY) {
758         LOGE("not meida authority.");
759         return -EINVAL;
760     }
761     std::string mediaSandboxPath = GetMediaSandboxPath(physicalPath, usrId);
762     if (mediaSandboxPath == "") {
763         LOGE("mediaSandboxPath is null.");
764         return -EINVAL;
765     }
766     hui.uriStr = FILE_SCHEME + "://" + MEDIA_BUNDLE_NAME + DISTRIBUTED_DIR_PATH + REMOTE_SHARE_PATH_DIR + BACKSLASH +
767         networkId + mediaSandboxPath + NETWORK_PARA + networkId;
768     return SetFileSize(physicalPath, hui);
769 }
770 
771 
GetMediaDfsUrisDirFromLocal(const std::vector<std::string> & uriList,const int32_t & userId,std::unordered_map<std::string,HmdfsUriInfo> & uriToDfsUriMaps)772 static int32_t GetMediaDfsUrisDirFromLocal(const std::vector<std::string> &uriList, const int32_t &userId,
773     std::unordered_map<std::string, HmdfsUriInfo> &uriToDfsUriMaps)
774 {
775     if (uriList.size() <= 0) {
776         LOGE("Failed to uri GetMediaDfsDirFromLocal, list is null or empty");
777         return -EINVAL;
778     }
779 
780     std::string networkId = GetLocalNetworkId();
781     std::string distributedDir;
782     int ret = GetMediaDistributedDir(userId, distributedDir, networkId);
783     if (ret != E_OK) {
784         LOGE("Failed to uri get distribute dir.");
785         return ret;
786     }
787 
788     std::string physicalDir = "";
789     ret = GetMediaPhysicalDir(userId, physicalDir, MEDIA_BUNDLE_NAME);
790     if (ret != E_OK) {
791         LOGE("Failed to uri get physical dir.");
792         return ret;
793     }
794 
795     ret = MountDisFileShare(userId, distributedDir, physicalDir);
796     if (ret != E_OK) {
797         LOGE("Failed to mount.");
798         return ret;
799     }
800 
801     std::vector<std::string> physicalPaths;
802     int getPhysicalPathRet = SandboxHelper::GetMediaSharePath(uriList, physicalPaths);
803     if (getPhysicalPathRet != E_OK) {
804         LOGE("Failed to get physical path.");
805         return -EINVAL;
806     }
807     for (size_t i = 0; i < uriList.size(); i++) {
808         Uri uri(uriList[i]);
809         HmdfsUriInfo dfsUriInfo;
810         SetMediaHmdfsUriDirInfo(dfsUriInfo, uri, physicalPaths[i], networkId, std::to_string(userId));
811         uriToDfsUriMaps.insert({uriList[i], dfsUriInfo});
812         LOGI("dfsUri: %{private}s", dfsUriInfo.uriStr.c_str());
813     }
814     return E_OK;
815 }
816 
DoMount(const int & userId,const std::string & bundleName,const std::string & networkId,Uri uri)817 static int32_t DoMount(const int &userId, const std::string &bundleName, const std::string &networkId, Uri uri)
818 {
819     std::string distributedDir;
820     int32_t ret = GetDistributedDir(userId, distributedDir, bundleName, networkId, uri);
821     if (ret != E_OK) {
822         LOGE("Failed to get distributed dir.");
823         return ret;
824     }
825 
826     std::string physicalDir = GetPhysicalDir(uri, userId);
827     if (physicalDir == "") {
828         LOGE("Failed to get physicalDir dir.");
829         return -EINVAL;
830     }
831 
832     ret = MountDisFileShare(userId, distributedDir, physicalDir);
833     if (ret != E_OK) {
834         LOGE("Failed to mount, errno: %{public}d.", ret);
835         return ret;
836     }
837     return E_OK;
838 }
839 
CheckIfNeedMount(const std::string & bundleName,const std::string & networkId,Uri uri,const std::string & physicalPath,std::unordered_map<std::string,HmdfsUriInfo> & uriToDfsUriMaps)840 static int32_t CheckIfNeedMount(const std::string &bundleName, const std::string &networkId, Uri uri,
841     const std::string &physicalPath, std::unordered_map<std::string, HmdfsUriInfo> &uriToDfsUriMaps)
842 {
843     HmdfsUriInfo dfsUriInfo;
844     std::string uriStr = uri.ToString();
845     if (bundleName == FILE_MANAGER_AUTHORITY) {
846         (void)SetPublicDirHmdfsInfo(physicalPath, uriStr, dfsUriInfo, networkId);
847         uriToDfsUriMaps.insert({uriStr, dfsUriInfo});
848         LOGI("bundleName: %{public}s, dfsUri: %{private}s", uriStr.c_str(), dfsUriInfo.uriStr.c_str());
849         return E_OK;
850     }
851     if (IsDistributedFileDir(uri) || IsCloudFileDir(uri)) {
852         (void)SetDistributedfilesHmdfsUriDirInfo(physicalPath, uriStr, dfsUriInfo, networkId);
853         uriToDfsUriMaps.insert({uriStr, dfsUriInfo});
854         LOGI("bundleName: %{public}s, dfsUri: %{private}s", uriStr.c_str(), dfsUriInfo.uriStr.c_str());
855         return E_OK;
856     }
857     return -EINVAL;
858 }
859 
GetDfsUrisDirFromLocal(const std::vector<std::string> & uriList,const int32_t & userId,std::unordered_map<std::string,HmdfsUriInfo> & uriToDfsUriMaps)860 int32_t RemoteFileShare::GetDfsUrisDirFromLocal(const std::vector<std::string> &uriList, const int32_t &userId,
861     std::unordered_map<std::string, HmdfsUriInfo> &uriToDfsUriMaps)
862 {
863     std::vector<std::string> otherUriList;
864     std::vector<std::string> mediaUriList;
865     int32_t ret = UriCategoryByType(uriList, mediaUriList, otherUriList);
866     if (ret == E_OK && mediaUriList.size() != 0) {
867         ret = GetMediaDfsUrisDirFromLocal(mediaUriList, userId, uriToDfsUriMaps);
868     }
869     if (ret != E_OK) {
870         LOGE("uri category failed or process media uri failed.");
871         return ret;
872     }
873     std::string networkId = GetLocalNetworkId();
874     for (const auto &uriStr : otherUriList) {
875         Uri uri(uriStr);
876         std::string physicalPath = GetPhysicalPath(uri, std::to_string(userId));
877         if (physicalPath == "") {
878             LOGE("Failed to get physical path");
879             return -EINVAL;
880         }
881 
882         std::string bundleName = uri.GetAuthority();
883         ret = CheckIfNeedMount(bundleName, networkId, uri, physicalPath, uriToDfsUriMaps);
884         if (ret == E_OK) {
885             continue;
886         }
887 
888         ret = DoMount(userId, bundleName, networkId, uri);
889         if (ret != E_OK) {
890             LOGE("Failed to mount, %{public}d", ret);
891             return ret;
892         }
893         HmdfsUriInfo dfsUriInfo;
894         (void)SetHmdfsUriDirInfo(dfsUriInfo, uri, physicalPath, networkId, bundleName);
895         uriToDfsUriMaps.insert({uriStr, dfsUriInfo});
896         LOGI("bundleName: %{public}s, dfsUri: %{private}s", bundleName.c_str(), dfsUriInfo.uriStr.c_str());
897     }
898     LOGI("GetDfsUrisDirFromLocal successfully");
899     return E_OK;
900 }
901 
TransRemoteUriToLocal(const std::vector<std::string> & uriList,const std::string & networkId,const std::string & deviceId,std::vector<std::string> & resultList)902 int32_t RemoteFileShare::TransRemoteUriToLocal(const std::vector<std::string> &uriList,
903                                                const std::string &networkId,
904                                                const std::string &deviceId,
905                                                std::vector<std::string> &resultList)
906 {
907     if (networkId.empty() || deviceId.empty()) {
908         LOGE("RemoteFileShare::TransRemoteUriToLocal, invalid argument with %{public}d", EINVAL);
909         return EINVAL;
910     }
911     constexpr int splitThree = 3;
912     bool allValid = true;
913     std::vector<std::string> tmpResultList;
914     for (auto &uriStr : uriList) {
915         Uri uri(uriStr);
916         std::string bundleName = uri.GetAuthority();
917         std::string sandboxPath = SandboxHelper::Decode(uri.GetPath());
918         if (!SandboxHelper::IsValidPath(sandboxPath) || uri.GetScheme() != FILE_SCHEME) {
919             LOGE("Sandbox path from uri is error");
920             allValid = false;
921             break;
922         }
923         if ((bundleName != FILE_MANAGER_AUTHORITY) || (sandboxPath.find(FILE_MANAGER_URI_HEAD) != 0)) {
924             LOGE("Sandbox path doesn't begin with docs/storage");
925             allValid = false;
926             break;
927         }
928         int cnt = 0;
929         size_t pos = 0;
930         std::string part;
931         while (cnt < splitThree && pos != std::string::npos) {
932             pos = sandboxPath.find('/', pos + 1);
933             cnt++;
934         }
935         if (pos != std::string::npos) {
936             part = sandboxPath.substr(pos + 1);
937         }
938         if (part.empty()) {
939             allValid = false;
940             break;
941         }
942         std::string localUri = FILE_SCHEME + "://" + bundleName + FILE_MANAGER_URI_HEAD +
943                                REMOTE_SHARE_PATH_MID + deviceId + "/" + part;
944         tmpResultList.push_back(localUri);
945     }
946     if (!allValid) {
947         LOGW("Failed to update uriList");
948         resultList = uriList;
949         return -EINVAL;
950     }
951     resultList = tmpResultList;
952     return E_OK;
953 }
954 } // namespace ModuleRemoteFileShare
955 } // namespace AppFileService
956 } // namespace OHOS
957