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 #include "open_core.h"
16
17 #include <cstdio>
18 #include <cstdlib>
19 #include <cstring>
20
21 #include "file_entity.h"
22 #include "file_instantiator.h"
23 #include "file_utils.h"
24 #include "filemgmt_libhilog.h"
25 #include "fs_utils.h"
26 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
27 #include "ability_manager_client.h"
28 #include "bundle_info.h"
29 #include "bundle_mgr_proxy.h"
30 #include "datashare_helper.h"
31 #include "file_uri.h"
32 #include "ipc_skeleton.h"
33 #include "iservice_registry.h"
34 #include "remote_uri.h"
35 #include "status_receiver_host.h"
36 #include "system_ability_definition.h"
37 #endif
38
39 #ifdef FILE_API_TRACE
40 #include "hitrace_meter.h"
41 #endif
42
43 namespace OHOS {
44 namespace FileManagement {
45 namespace ModuleFileIO {
46 using namespace std;
47
48 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
49 using namespace OHOS::DistributedFS::ModuleRemoteUri;
50 using namespace OHOS::AppExecFwk;
51 #endif
52
53 const std::string PROCEDURE_OPEN_NAME = "FileIOOpen";
54 const std::string MEDIALIBRARY_DATA_URI = "datashare:///media";
55 const std::string FILE_DATA_URI = "file://";
56 const std::string PATH_SHARE = "/data/storage/el2/share";
57 const std::string MODE_RW = "/rw/";
58 const std::string MODE_R = "/r/";
59 const std::string MEDIA = "media";
60 const std::string DOCS = "docs";
61 const std::string DATASHARE = "datashare";
62 const std::string SCHEME_BROKER = "content";
63 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
64 constexpr uint32_t MAX_WANT_FLAG = 4;
65 #endif
66
ValidAndConvertFlags(const optional<int32_t> & mode)67 static tuple<bool, uint32_t> ValidAndConvertFlags(const optional<int32_t> &mode)
68 {
69 uint32_t flags = O_RDONLY;
70 if (mode.has_value()) {
71 auto modeValue = mode.value();
72 if (modeValue < 0) {
73 HILOGE("Invalid mode");
74 return { false, flags };
75 }
76 flags = static_cast<uint32_t>(modeValue);
77 uint32_t invalidMode = (O_WRONLY | O_RDWR);
78 if ((flags & invalidMode) == invalidMode) {
79 HILOGE("Invalid mode");
80 return { false, flags };
81 }
82 flags = FsUtils::ConvertFlags(flags);
83 }
84 return { true, flags };
85 }
86
OpenFileByPath(const string & path,uint32_t mode)87 static int OpenFileByPath(const string &path, uint32_t mode)
88 {
89 unique_ptr<uv_fs_t, decltype(FsUtils::FsReqCleanup) *> openReq = { new uv_fs_t, FsUtils::FsReqCleanup };
90 if (!openReq) {
91 HILOGE("Failed to request heap memory.");
92 return -ENOMEM;
93 }
94 int ret = uv_fs_open(nullptr, openReq.get(), path.c_str(), mode, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, nullptr);
95 return ret;
96 }
97
98 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
99
OpenFileByDatashare(const string & path,uint32_t flags)100 static int OpenFileByDatashare(const string &path, uint32_t flags)
101 {
102 std::shared_ptr<DataShare::DataShareHelper> dataShareHelper = nullptr;
103 sptr<FileIoToken> remote = new (std::nothrow) IRemoteStub<FileIoToken>();
104 if (!remote) {
105 HILOGE("Failed to get remote object");
106 return -ENOMEM;
107 }
108
109 dataShareHelper = DataShare::DataShareHelper::Creator(remote->AsObject(), MEDIALIBRARY_DATA_URI);
110 if (!dataShareHelper) {
111 HILOGE("Failed to connect to datashare");
112 return -E_PERMISSION;
113 }
114
115 Uri uri(path);
116 int fd = dataShareHelper->OpenFile(uri, FsUtils::GetModeFromFlags(flags));
117 return fd;
118 }
119
OpenByFileDataUri(Uri & uri,const string & uriStr,uint32_t mode)120 static tuple<int, string> OpenByFileDataUri(Uri &uri, const string &uriStr, uint32_t mode)
121 {
122 string bundleName = uri.GetAuthority();
123 AppFileService::ModuleFileUri::FileUri fileUri(uriStr);
124 string realPath = fileUri.GetRealPath();
125 if (bundleName == MEDIA) {
126 int res = OpenFileByDatashare(uri.ToString(), mode);
127 if (res < 0) {
128 HILOGE("Failed to open file by Datashare error %{public}d", res);
129 }
130 return { res, uri.ToString() };
131 } else if (bundleName == DOCS && access(realPath.c_str(), F_OK) != 0) {
132 int res = OpenFileByDatashare(uri.ToString(), mode);
133 if (res < 0) {
134 HILOGE("Failed to open file by Datashare error %{public}d", res);
135 return { -ENOENT, uri.ToString() };
136 }
137 return { res, uri.ToString() };
138 }
139 int ret = OpenFileByPath(realPath, mode);
140 if (ret < 0) {
141 HILOGE("Failed to open file for libuv error %{public}d", ret);
142 }
143 return { ret, uriStr };
144 }
145
OpenFileByBroker(const Uri & uri,uint32_t mode)146 static tuple<int, string> OpenFileByBroker(const Uri &uri, uint32_t mode)
147 {
148 uint32_t flag = (mode % MAX_WANT_FLAG) > 0 ? AAFwk::Want::FLAG_AUTH_WRITE_URI_PERMISSION
149 : AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION;
150 int ret = AAFwk::AbilityManagerClient::GetInstance()->OpenFile(uri, flag);
151 if (ret < 0) {
152 HILOGE("Failed to open file by Broker error %{public}d", ret);
153 }
154 return { ret, uri.ToString() };
155 }
156
OpenFileByUri(const string & path,uint32_t mode)157 static tuple<int, string> OpenFileByUri(const string &path, uint32_t mode)
158 {
159 Uri uri(path);
160 string uriType = uri.GetScheme();
161 if (uriType == SCHEME_FILE) {
162 return OpenByFileDataUri(uri, path, mode);
163 }
164 if (uriType == SCHEME_BROKER) {
165 return OpenFileByBroker(uri, mode);
166 }
167 int fd = -1;
168 if (uriType == DATASHARE && RemoteUri::IsRemoteUri(path, fd, mode)) {
169 if (fd >= 0) {
170 return { fd, path };
171 }
172 HILOGE("Failed to open file by RemoteUri");
173 }
174 HILOGE("Failed to open file by invalid uri");
175 return { -EINVAL, path };
176 }
177 #endif
178
DoOpen(const string & path,const optional<int32_t> & mode)179 FsResult<FsFile *> OpenCore::DoOpen(const string &path, const optional<int32_t> &mode)
180 {
181 #ifdef FILE_API_TRACE
182 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
183 #endif
184 auto [succMode, modeValue] = ValidAndConvertFlags(mode);
185 if (!succMode) {
186 return FsResult<FsFile *>::Error(EINVAL);
187 }
188 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
189 if (path.find("://") != string::npos) {
190 auto [res, uriStr] = OpenFileByUri(path, modeValue);
191 if (res < 0) {
192 return FsResult<FsFile *>::Error(res);
193 }
194 return FileInstantiator::InstantiateFile(res, uriStr, true);
195 }
196 #endif
197 int ret = OpenFileByPath(path, modeValue);
198 if (ret < 0) {
199 HILOGD("Failed to open file for libuv error %{public}d", ret);
200 return FsResult<FsFile *>::Error(ret);
201 }
202 return FileInstantiator::InstantiateFile(ret, path, false);
203 }
204
205 } // namespace ModuleFileIO
206 } // namespace FileManagement
207 } // namespace OHOS