• 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 "access_core.h"
17 
18 #include <unistd.h>
19 
20 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
21 #include <sys/xattr.h>
22 
23 #include "bundle_mgr_proxy.h"
24 #include "if_system_ability_manager.h"
25 #include "ipc_skeleton.h"
26 #include "iservice_registry.h"
27 #include "rust_file.h"
28 #include "system_ability_definition.h"
29 
30 #endif
31 
32 #ifdef FILE_API_TRACE
33 #include "hitrace_meter.h"
34 #endif
35 
36 #include "filemgmt_libhilog.h"
37 
38 namespace OHOS {
39 namespace FileManagement {
40 namespace ModuleFileIO {
41 using namespace std;
42 using namespace AppExecFwk;
43 
44 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
45 const string CLOUDDISK_FILE_PREFIX = "/data/storage/el2/cloud";
46 const string DISTRIBUTED_FILE_PREFIX = "/data/storage/el2/distributedfiles";
47 const string PACKAGE_NAME_FLAG = "<PackageName>";
48 const string USER_ID_FLAG = "<currentUserId>";
49 const string PHYSICAL_PATH_PREFIX = "/mnt/hmdfs/<currentUserId>/account/device_view/local/data/<PackageName>";
50 const string CLOUD_FILE_LOCATION = "user.cloud.location";
51 const char POSITION_LOCAL = '1';
52 const char POSITION_BOTH = '3';
53 const int BASE_USER_RANGE = 200000;
54 #endif
55 
UvAccess(const string & path,int mode)56 static int UvAccess(const string &path, int mode)
57 {
58     std::unique_ptr<uv_fs_t, decltype(FsUtils::FsReqCleanup) *> accessReq = {new uv_fs_t, FsUtils::FsReqCleanup};
59     if (!accessReq) {
60         HILOGE("Failed to request heap memory.");
61         return ENOMEM;
62     }
63     return uv_fs_access(nullptr, accessReq.get(), path.c_str(), mode, nullptr);
64 }
65 
66 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
IsCloudOrDistributedFilePath(const string & path)67 static bool IsCloudOrDistributedFilePath(const string &path)
68 {
69     return path.find(CLOUDDISK_FILE_PREFIX) == 0 || path.find(DISTRIBUTED_FILE_PREFIX) == 0;
70 }
71 
GetCurrentUserId()72 static int GetCurrentUserId()
73 {
74     int uid = IPCSkeleton::GetCallingUid();
75     int userId = uid / BASE_USER_RANGE;
76     return userId;
77 }
78 
GetBundleMgrProxy()79 static sptr<BundleMgrProxy> GetBundleMgrProxy()
80 {
81     sptr<ISystemAbilityManager> systemAbilityManager =
82         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
83     if (!systemAbilityManager) {
84         HILOGE("fail to get system ability mgr");
85         return nullptr;
86     }
87     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
88     if (!remoteObject) {
89         HILOGE("fail to get bundle manager proxy");
90         return nullptr;
91     }
92 
93     return iface_cast<BundleMgrProxy>(remoteObject);
94 }
95 
GetSelfBundleName()96 static string GetSelfBundleName()
97 {
98     sptr<BundleMgrProxy> bundleMgrProxy = GetBundleMgrProxy();
99     if (!bundleMgrProxy) {
100         HILOGE("bundleMgrProxy is nullptr");
101         return "";
102     }
103     BundleInfo bundleInfo;
104     auto ret = bundleMgrProxy->GetBundleInfoForSelf(0, bundleInfo);
105     if (ret != 0) {
106         HILOGE("bundleName get fail");
107         return "";
108     }
109     return bundleInfo.name;
110 }
111 
HandleLocalCheck(const string & path,int mode)112 static int HandleLocalCheck(const string &path, int mode)
113 {
114     // check if the file of /data/storage/el2/cloud is on the local
115     if (path.find(CLOUDDISK_FILE_PREFIX) == 0) {
116         char val[2] = {'\0'};
117         if (getxattr(path.c_str(), CLOUD_FILE_LOCATION.c_str(), val, sizeof(val)) < 0) {
118             HILOGI("get cloud file location fail, err: %{public}d", errno);
119             return errno;
120         }
121         if (val[0] == POSITION_LOCAL || val[0] == POSITION_BOTH) {
122             return 0;
123         }
124         return ENOENT;
125     }
126     // check if the distributed file of /data/storage/el2/distributedfiles is on the local,
127     // convert into physical path(/mnt/hmdfs/<currentUserId>/account/device_view/local/data/<PackageName>) and check
128     if (path.find(DISTRIBUTED_FILE_PREFIX) == 0) {
129         int userId = GetCurrentUserId();
130         string bundleName = GetSelfBundleName();
131         string relativePath = path.substr(DISTRIBUTED_FILE_PREFIX.length());
132         string physicalPath = PHYSICAL_PATH_PREFIX + relativePath;
133         physicalPath.replace(physicalPath.find(USER_ID_FLAG), USER_ID_FLAG.length(), to_string(userId));
134         physicalPath.replace(physicalPath.find(PACKAGE_NAME_FLAG), PACKAGE_NAME_FLAG.length(), bundleName);
135 
136         return UvAccess(physicalPath, mode);
137     }
138 
139     return ENOENT;
140 }
141 #endif
142 
Access(const string & path,int mode,int flag)143 static int Access(const string &path, int mode, int flag)
144 {
145 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
146     if (flag == LOCAL_FLAG && IsCloudOrDistributedFilePath(path)) {
147         return HandleLocalCheck(path, mode);
148     }
149 #endif
150     return UvAccess(path, mode);
151 }
152 
GetMode(const std::optional<AccessModeType> & modeOpt,bool * hasMode)153 static int GetMode(const std::optional<AccessModeType> &modeOpt, bool *hasMode)
154 {
155     if (modeOpt.has_value()) {
156         int mode = static_cast<int>(modeOpt.value());
157         *hasMode = true;
158         if ((static_cast<unsigned int>(mode) & 0x06) == static_cast<unsigned int>(mode)) {
159             return mode;
160         }
161     }
162 
163     return -1;
164 }
165 
ValidAccessArgs(const std::string & path,const std::optional<AccessModeType> & modeOpt,int & finalMode)166 static bool ValidAccessArgs(const std::string &path, const std::optional<AccessModeType> &modeOpt,
167                             int &finalMode)
168 {
169     if (path.empty()) {
170         HILOGE("Invalid path");
171         return false;
172     }
173     bool hasMode = false;
174     int mode = GetMode(modeOpt, &hasMode);
175     if (mode < 0 && hasMode) {
176         HILOGE("Invalid mode");
177         return false;
178     }
179     finalMode = hasMode ? mode : 0;
180     return true;
181 }
182 
DoAccess(const std::string & path,const std::optional<AccessModeType> & mode)183 FsResult<bool> AccessCore::DoAccess(const std::string& path, const std::optional<AccessModeType> &mode)
184 {
185     int finalMode = 0;
186     int flag = DEFAULT_FLAG;
187     if (!ValidAccessArgs(path, mode, finalMode)) {
188         return FsResult<bool>::Error(EINVAL);
189     }
190     int ret = Access(path, finalMode, flag);
191     if (ret < 0 && (std::string_view(uv_err_name(ret)) != "ENOENT")) {
192         HILOGE("Failed to access file by path");
193         return FsResult<bool>::Error(ret);
194     }
195     bool isAccess = (ret == 0);
196     return FsResult<bool>::Success(isAccess);
197 }
198 
DoAccess(const std::string & path,const AccessModeType & mode,const AccessFlag & flag)199 FsResult<bool> AccessCore::DoAccess(const std::string& path, const AccessModeType &mode, const AccessFlag &flag)
200 {
201     int finalMode = static_cast<int>(mode);
202     int finalFlag = static_cast<int>(flag);
203     if (!ValidAccessArgs(path, std::make_optional(mode), finalMode)) {
204         return FsResult<bool>::Error(EINVAL);
205     }
206     int ret = Access(path, finalMode, finalFlag);
207     if (ret < 0 && (std::string_view(uv_err_name(ret)) != "ENOENT")) {
208         HILOGE("Failed to access file by path");
209         return FsResult<bool>::Error(ret);
210     }
211     bool isAccess = (ret == 0);
212     return FsResult<bool>::Success(isAccess);
213 }
214 
215 } // namespace ModuleFileIO
216 } // namespace FileManagement
217 } // namespace OHOS