1 /*
2 * Copyright (c) 2024 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 "ohos_file.h"
17
18 #include <cstdint>
19
20 #include <cerrno>
21 #include <dirent.h>
22
23 #ifndef _DIRENT_HAVE_D_TYPE
24 #include <sys/stat.h>
25 #include <sys/types.h>
26
27 #endif
28 #include <climits>
29 #define CORE_MAX_PATH PATH_MAX
30
31 #include <base/containers/string.h>
32 #include <base/containers/string_view.h>
33 #include <core/io/intf_file.h>
34 #include <core/log.h>
35 #include <core/namespace.h>
36
37 #include "io/std_directory.h"
38
39 CORE_BEGIN_NAMESPACE()
40 using BASE_NS::CloneData;
41 using BASE_NS::string;
42 using BASE_NS::string_view;
43
44 const std::regex MEDIA_RES_ID_REGEX(R"(^\w+/([0-9]+)\.\w+$)", std::regex::icase);
45 const std::regex MEDIA_HAP_RES_PATH_REGEX(R"(^(.*)$)");
46 const std::regex MEDIA_HAP_RES_ID_REGEX(R"(^.*/([0-9]+)\.\w+$)", std::regex::icase);
47 const std::regex MEDIA_RES_NAME_REGEX(R"(^.*/(\w+)\.\w+$)", std::regex::icase);
48
49 constexpr uint32_t OHOS_RESOURCE_MATCH_SIZE = 2;
50
UpdateResManager(const PlatformHapInfo & hapInfo)51 void OhosResMgr::UpdateResManager(const PlatformHapInfo& hapInfo)
52 {
53 auto key = hapInfo.bundleName + "+" + hapInfo.moduleName;
54 auto resourceMgrIter = resourceManagers_.find(key);
55 if (resourceMgrIter != resourceManagers_.end()) {
56 resourceManager_ = resourceMgrIter->second;
57 return;
58 }
59
60 if (hapInfo.resourceManager != nullptr) {
61 resourceManagers_[key] = hapInfo.resourceManager;
62 resourceManager_ = hapInfo.resourceManager;
63 CORE_LOG_D("resource manager has ready by new api");
64 return;
65 }
66
67 std::shared_ptr<OHOS::Global::Resource::ResourceManager>
68 newResMgr(OHOS::Global::Resource::CreateResourceManager());
69 auto resRet = newResMgr->AddResource(hapInfo.hapPath.c_str());
70 resourceManagers_[key] = newResMgr;
71 resourceManager_ = newResMgr;
72 }
73
GetResMgr() const74 std::shared_ptr<OHOS::Global::Resource::ResourceManager> OhosResMgr::GetResMgr() const
75 {
76 return resourceManager_;
77 }
78
OhosFileDirectory(BASE_NS::refcnt_ptr<OhosResMgr> resMgr)79 OhosFileDirectory::OhosFileDirectory(BASE_NS::refcnt_ptr<OhosResMgr> resMgr) : dirResMgr_(resMgr) {}
80
~OhosFileDirectory()81 OhosFileDirectory::~OhosFileDirectory()
82 {
83 Close();
84 }
85
Close()86 void OhosFileDirectory::Close()
87 {
88 if (dir_) {
89 dir_.reset();
90 }
91 }
92
IsDir(BASE_NS::string_view path,std::vector<std::string> & fileList) const93 bool OhosFileDirectory::IsDir(BASE_NS::string_view path, std::vector<std::string>& fileList) const
94 {
95 auto state = dirResMgr_->GetResMgr()->GetRawFileList(path.data(), fileList);
96 if (state != OHOS::Global::Resource::SUCCESS || fileList.empty()) {
97 CORE_LOG_E("GetRawfilepath error, filename:%s, error:%u", path.data(), state);
98 return false;
99 }
100 return true;
101 }
102
IsFile(BASE_NS::string_view path) const103 bool OhosFileDirectory::IsFile(BASE_NS::string_view path) const
104 {
105 std::unique_ptr<uint8_t[]> data;
106 size_t dataLen = 0;
107 auto state = dirResMgr_->GetResMgr()->GetRawFileFromHap(path.data(), dataLen, data);
108 if (state != OHOS::Global::Resource::SUCCESS) {
109 return false;
110 }
111 return true;
112 }
113
Open(const BASE_NS::string_view pathIn)114 bool OhosFileDirectory::Open(const BASE_NS::string_view pathIn)
115 {
116 auto path = pathIn;
117 if (path.back() == '/') {
118 path.remove_suffix(1);
119 }
120 if (path.front() == '/') {
121 path.remove_prefix(1);
122 }
123 std::vector<std::string> fileList;
124 if (IsDir(path, fileList)) {
125 dir_ = BASE_NS::make_unique<OhosDirImpl>(path, fileList);
126 return true;
127 }
128 return false;
129 }
130
GetEntries() const131 BASE_NS::vector<IDirectory::Entry> OhosFileDirectory::GetEntries() const
132 {
133 CORE_ASSERT_MSG(dir_, "Dir not open");
134 BASE_NS::vector<IDirectory::Entry> result;
135 if (dir_) {
136 for (int i = 0; i < static_cast<int>(dir_->fileList_.size()); i++) {
137 auto path = dir_->path_ + "/" + BASE_NS::string(dir_->fileList_[i].c_str());
138 auto entry = GetEntry(path);
139 entry.timestamp = static_cast<uint32_t>(i);
140 entry.name = dir_->fileList_[i].c_str();
141 result.emplace_back(entry);
142 }
143 }
144 return result;
145 }
146
GetEntry(BASE_NS::string_view uriIn) const147 IDirectory::Entry OhosFileDirectory::GetEntry(BASE_NS::string_view uriIn) const
148 {
149 if (!uriIn.empty()) {
150 IDirectory::Entry::Type type;
151 std::vector<std::string> fileList;
152 if (IsFile(uriIn)) {
153 type = IDirectory::Entry::FILE;
154 } else if (IsDir(uriIn, fileList)) {
155 type = IDirectory::Entry::DIRECTORY;
156 } else {
157 type = IDirectory::Entry::UNKNOWN;
158 }
159 // timestamp set 0
160 uint64_t timestamp = 0;
161 BASE_NS::string entryName { uriIn };
162 return IDirectory::Entry { type, entryName, timestamp };
163 }
164 return {};
165 }
166
OhosFile(BASE_NS::refcnt_ptr<OhosResMgr> resMgr)167 OhosFile::OhosFile(BASE_NS::refcnt_ptr<OhosResMgr> resMgr) : fileResMgr_(resMgr)
168 {
169 buffer_ = std::make_shared<OhosFileStorage>(nullptr);
170 }
171
UpdateStorage(std::shared_ptr<OhosFileStorage> buffer)172 void OhosFile::UpdateStorage(std::shared_ptr<OhosFileStorage> buffer)
173 {
174 buffer_ = BASE_NS::move(buffer);
175 }
176
GetMode() const177 IFile::Mode OhosFile::GetMode() const
178 {
179 return IFile::Mode::READ_ONLY;
180 }
181
Close()182 void OhosFile::Close() {}
183
Read(void * buffer,uint64_t count)184 uint64_t OhosFile::Read(void* buffer, uint64_t count)
185 {
186 uint64_t toRead = count;
187 uint64_t sum = index_ + toRead;
188 if (sum < index_) {
189 return 0;
190 }
191 if (sum > buffer_->Size()) {
192 toRead = buffer_->Size() - index_;
193 }
194 if (toRead <= 0) {
195 return toRead;
196 }
197 if (toRead > SIZE_MAX) {
198 CORE_ASSERT_MSG(false, "Unable to read chunks bigger than (SIZE_MAX) bytes.");
199 return 0;
200 }
201 if (CloneData(buffer, static_cast<size_t>(count), &(buffer_->GetStorage()[index_]), static_cast<size_t>(toRead))) {
202 index_ += toRead;
203 }
204 return toRead;
205 }
206
Write(const void * buffer,uint64_t count)207 uint64_t OhosFile::Write(const void* buffer, uint64_t count)
208 {
209 return 0;
210 }
211
Append(const void * buffer,uint64_t count,uint64_t flushSize)212 uint64_t OhosFile::Append(const void* buffer, uint64_t count, uint64_t flushSize)
213 {
214 return 0;
215 }
216
GetLength() const217 uint64_t OhosFile::GetLength() const
218 {
219 return buffer_->Size();
220 }
221
Seek(uint64_t aOffset)222 bool OhosFile::Seek(uint64_t aOffset)
223 {
224 if (aOffset < buffer_->Size()) {
225 index_ = aOffset;
226 return true;
227 }
228 return false;
229 }
230
GetPosition() const231 uint64_t OhosFile::GetPosition() const
232 {
233 return index_;
234 }
235
Open(BASE_NS::string_view rawFile)236 std::shared_ptr<OhosFileStorage> OhosFile::Open(BASE_NS::string_view rawFile)
237 {
238 std::unique_ptr<uint8_t[]> data;
239 size_t dataLen = 0;
240 if (OpenRawFile(rawFile, dataLen, data)) {
241 buffer_->SetBuffer(std::move(data), static_cast<uint64_t>(dataLen));
242 return buffer_;
243 }
244 return nullptr;
245 }
246
247 // Parsing URI
GetResourceId(const std::string & uri,uint32_t & resId) const248 bool OhosFile::GetResourceId(const std::string& uri, uint32_t& resId) const
249 {
250 std::smatch matches;
251 if (std::regex_match(uri, matches, MEDIA_RES_ID_REGEX) && matches.size() == OHOS_RESOURCE_MATCH_SIZE) {
252 resId = static_cast<uint32_t>(std::stoul(matches[1].str()));
253 return true;
254 }
255 std::smatch hapMatches;
256 if (std::regex_match(uri, hapMatches, MEDIA_HAP_RES_ID_REGEX) && hapMatches.size() == OHOS_RESOURCE_MATCH_SIZE) {
257 resId = static_cast<uint32_t>(std::stoul(hapMatches[1].str()));
258 return true;
259 }
260 return false;
261 }
262
GetResourceId(const std::string & uri,std::string & path) const263 bool OhosFile::GetResourceId(const std::string& uri, std::string& path) const
264 {
265 std::smatch matches;
266 if (std::regex_match(uri, matches, MEDIA_HAP_RES_PATH_REGEX) && matches.size() == OHOS_RESOURCE_MATCH_SIZE) {
267 path = matches[1].str();
268 return true;
269 }
270 return false;
271 }
272
GetResourceName(const std::string & uri,std::string & resName) const273 bool OhosFile::GetResourceName(const std::string& uri, std::string& resName) const
274 {
275 std::smatch matches;
276 if (std::regex_match(uri, matches, MEDIA_RES_NAME_REGEX) && matches.size() == OHOS_RESOURCE_MATCH_SIZE) {
277 resName = matches[1].str();
278 return true;
279 }
280 return false;
281 }
282
OpenRawFile(BASE_NS::string_view uriIn,size_t & dataLen,std::unique_ptr<uint8_t[]> & dest)283 bool OhosFile::OpenRawFile(BASE_NS::string_view uriIn, size_t& dataLen, std::unique_ptr<uint8_t[]>& dest)
284 {
285 std::string uri(uriIn.data());
286 std::string rawFile;
287 if (GetResourceId(uri, rawFile)) {
288 auto state = fileResMgr_->GetResMgr()->GetRawFileFromHap(rawFile.c_str(), dataLen, dest);
289 if (state != OHOS::Global::Resource::SUCCESS || !dest) {
290 CORE_LOG_E("GetRawFileFromHap error, raw filename:%s, error:%u", rawFile.c_str(), state);
291 return false;
292 }
293 return true;
294 }
295 uint32_t resId = 0;
296 if (GetResourceId(uri, resId)) {
297 auto state = fileResMgr_->GetResMgr()->GetMediaDataById(resId, dataLen, dest);
298 if (state != OHOS::Global::Resource::SUCCESS || !dest) {
299 CORE_LOG_E("GetMediaDataById error, resId:%u, error:%u", resId, state);
300 return false;
301 }
302 return true;
303 }
304 std::string resName;
305 if (GetResourceName(uri, resName)) {
306 auto state = fileResMgr_->GetResMgr()->GetMediaDataByName(resName.c_str(), dataLen, dest);
307 if (state != OHOS::Global::Resource::SUCCESS || !dest) {
308 CORE_LOG_E("GetMediaDataByName error, resName:%s, error:%u", resName.c_str(), state);
309 return false;
310 }
311 return true;
312 }
313 CORE_LOG_E("load image data failed, as uri is invalid:%s", uri.c_str());
314 return false;
315 }
316 CORE_END_NAMESPACE()
317