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