1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 *
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12
13 * * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15 * either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations
18 * under the License.
19 */
20
21 #include "ohos_file.h"
22
23 #include <cstdint>
24
25 #ifdef __has_include
26 #if __has_include(<filesystem>)
27 #include <filesystem>
28 #define HAS_FILESYSTEM
29 #endif
30 #endif
31
32 #ifndef HAS_FILESYSTEM
33 #include <cerrno>
34 #include <dirent.h>
35
36 #ifndef _DIRENT_HAVE_D_TYPE
37 #include <sys/stat.h>
38 #include <sys/types.h>
39
40 #endif
41 #include <climits>
42 #define CORE_MAX_PATH PATH_MAX
43 #endif
44
45 #include <base/containers/string.h>
46 #include <base/containers/string_view.h>
47 #include <core/io/intf_file.h>
48 #include <core/log.h>
49 #include <core/namespace.h>
50
51 #include "io/std_directory.h"
52
53 CORE_BEGIN_NAMESPACE()
54 using BASE_NS::CloneData;
55 using BASE_NS::string;
56 using BASE_NS::string_view;
57
58 const std::regex MEDIA_RES_ID_REGEX(R"(^\w+/([0-9]+)\.\w+$)", std::regex::icase);
59 const std::regex MEDIA_HAP_RES_PATH_REGEX(R"(^(.*)$)");
60 const std::regex MEDIA_HAP_RES_ID_REGEX(R"(^.*/([0-9]+)\.\w+$)", std::regex::icase);
61 const std::regex MEDIA_RES_NAME_REGEX(R"(^.*/(\w+)\.\w+$)", std::regex::icase);
62
63 constexpr uint32_t OHOS_RESOURCE_MATCH_SIZE = 2;
64
UpdateResManager(const PlatformHapInfo & hapInfo)65 void OhosResMgr::UpdateResManager(const PlatformHapInfo& hapInfo)
66 {
67 auto key = hapInfo.bundleName + "+" + hapInfo.moduleName;
68 auto resourceMgrIter = resourceManagers_.find(key);
69 if (resourceMgrIter != resourceManagers_.end()) {
70 resourceManager_ = resourceMgrIter->second;
71 return;
72 }
73 std::shared_ptr<OHOS::Global::Resource::ResourceManager>
74 newResMgr(OHOS::Global::Resource::CreateResourceManager());
75 auto resRet = newResMgr->AddResource(hapInfo.hapPath.c_str());
76 resourceManagers_[key] = newResMgr;
77 resourceManager_ = newResMgr;
78 }
79
GetResMgr() const80 std::shared_ptr<OHOS::Global::Resource::ResourceManager> OhosResMgr::GetResMgr() const
81 {
82 return resourceManager_;
83 }
84
OhosFileDirectory(BASE_NS::refcnt_ptr<OhosResMgr> resMgr)85 OhosFileDirectory::OhosFileDirectory(BASE_NS::refcnt_ptr<OhosResMgr> resMgr) : dirResMgr_(resMgr) {}
86
~OhosFileDirectory()87 OhosFileDirectory::~OhosFileDirectory()
88 {
89 Close();
90 }
91
Close()92 void OhosFileDirectory::Close()
93 {
94 if (dir_) {
95 dir_.reset();
96 }
97 }
98
IsDir(BASE_NS::string_view path,std::vector<std::string> & fileList) const99 bool OhosFileDirectory::IsDir(BASE_NS::string_view path, std::vector<std::string>& fileList) const
100 {
101 auto state = dirResMgr_->GetResMgr()->GetRawFileList(path.data(), fileList);
102 if (state != OHOS::Global::Resource::SUCCESS || fileList.empty()) {
103 CORE_LOG_E("GetRawfilepath error, filename:%s, error:%u", path.data(), state);
104 return false;
105 }
106 return true;
107 }
108
IsFile(BASE_NS::string_view path) const109 bool OhosFileDirectory::IsFile(BASE_NS::string_view path) const
110 {
111 std::unique_ptr<uint8_t[]> data;
112 size_t dataLen = 0;
113 auto state = dirResMgr_->GetResMgr()->GetRawFileFromHap(path.data(), dataLen, data);
114 if (state != OHOS::Global::Resource::SUCCESS) {
115 return false;
116 }
117 return true;
118 }
119
Open(const BASE_NS::string_view pathIn)120 bool OhosFileDirectory::Open(const BASE_NS::string_view pathIn)
121 {
122 auto path = pathIn;
123 if (path.back() == '/') {
124 path.remove_suffix(1);
125 }
126 if (path.front() == '/') {
127 path.remove_prefix(1);
128 }
129 std::vector<std::string> fileList;
130 if (IsDir(path, fileList)) {
131 dir_ = BASE_NS::make_unique<OhosDirImpl>(path, fileList);
132 return true;
133 }
134 return false;
135 }
136
GetEntries() const137 BASE_NS::vector<IDirectory::Entry> OhosFileDirectory::GetEntries() const
138 {
139 CORE_ASSERT_MSG(dir_, "Dir not open");
140 BASE_NS::vector<IDirectory::Entry> result;
141 if (dir_) {
142 for (int i = 0; i < static_cast<int>(dir_->fileList_.size()); i++) {
143 auto path = dir_->path_ + "/" + BASE_NS::string(dir_->fileList_[i].c_str());
144 auto entry = GetEntry(path);
145 entry.timestamp = static_cast<uint32_t>(i);
146 entry.name = dir_->fileList_[i].c_str();
147 result.emplace_back(entry);
148 }
149 }
150 return result;
151 }
152
GetEntry(BASE_NS::string_view uriIn) const153 IDirectory::Entry OhosFileDirectory::GetEntry(BASE_NS::string_view uriIn) const
154 {
155 if (!uriIn.empty()) {
156 IDirectory::Entry::Type type;
157 std::vector<std::string> fileList;
158 if (IsFile(uriIn)) {
159 type = IDirectory::Entry::FILE;
160 } else if (IsDir(uriIn, fileList)) {
161 type = IDirectory::Entry::DIRECTORY;
162 } else {
163 type = IDirectory::Entry::UNKNOWN;
164 }
165 // timestamp set 0
166 uint64_t timestamp = 0;
167 BASE_NS::string entryName { uriIn };
168 return IDirectory::Entry { type, entryName, timestamp };
169 }
170 return {};
171 }
172
OhosFile(BASE_NS::refcnt_ptr<OhosResMgr> resMgr)173 OhosFile::OhosFile(BASE_NS::refcnt_ptr<OhosResMgr> resMgr) : fileResMgr_(resMgr)
174 {
175 buffer_ = std::make_shared<OhosFileStorage>(nullptr);
176 }
177
UpdateStorage(std::shared_ptr<OhosFileStorage> buffer)178 void OhosFile::UpdateStorage(std::shared_ptr<OhosFileStorage> buffer)
179 {
180 buffer_ = BASE_NS::move(buffer);
181 }
182
GetMode() const183 IFile::Mode OhosFile::GetMode() const
184 {
185 return IFile::Mode::READ_ONLY;
186 }
187
Close()188 void OhosFile::Close() {}
189
Read(void * buffer,uint64_t count)190 uint64_t OhosFile::Read(void* buffer, uint64_t count)
191 {
192 uint64_t toRead = count;
193 uint64_t sum = index_ + toRead;
194 if (sum < index_) {
195 return 0;
196 }
197 if (sum > buffer_->Size()) {
198 toRead = buffer_->Size() - index_;
199 }
200 if (toRead <= 0) {
201 return toRead;
202 }
203 if (toRead > SIZE_MAX) {
204 CORE_ASSERT_MSG(false, "Unable to read chunks bigger than (SIZE_MAX) bytes.");
205 return 0;
206 }
207 if (CloneData(buffer, static_cast<size_t>(count), &(buffer_->GetStorage()[index_]),
208 static_cast<size_t>(toRead))) {
209 index_ += toRead;
210 }
211 return toRead;
212 }
213
Write(const void * buffer,uint64_t count)214 uint64_t OhosFile::Write(const void* buffer, uint64_t count)
215 {
216 return 0;
217 }
218
GetLength() const219 uint64_t OhosFile::GetLength() const
220 {
221 return buffer_->Size();
222 }
223
Seek(uint64_t aOffset)224 bool OhosFile::Seek(uint64_t aOffset)
225 {
226 if (aOffset < buffer_->Size()) {
227 index_ = aOffset;
228 return true;
229 }
230 return false;
231 }
232
GetPosition() const233 uint64_t OhosFile::GetPosition() const
234 {
235 return index_;
236 }
237
Open(BASE_NS::string_view rawFile)238 std::shared_ptr<OhosFileStorage> OhosFile::Open(BASE_NS::string_view rawFile)
239 {
240 std::unique_ptr<uint8_t[]> data;
241 size_t dataLen = 0;
242 if (OpenRawFile(rawFile, dataLen, data)) {
243 buffer_->SetBuffer(std::move(data), static_cast<uint64_t>(dataLen));
244 return buffer_;
245 }
246 return nullptr;
247 }
248
249 // Parsing URI
GetResourceId(const std::string & uri,uint32_t & resId) const250 bool OhosFile::GetResourceId(const std::string& uri, uint32_t& resId) const
251 {
252 std::smatch matches;
253 if (std::regex_match(uri, matches, MEDIA_RES_ID_REGEX) && matches.size() == OHOS_RESOURCE_MATCH_SIZE) {
254 resId = static_cast<uint32_t>(std::stoul(matches[1].str()));
255 return true;
256 }
257 std::smatch hapMatches;
258 if (std::regex_match(uri, hapMatches, MEDIA_HAP_RES_ID_REGEX) && hapMatches.size() == OHOS_RESOURCE_MATCH_SIZE) {
259 resId = static_cast<uint32_t>(std::stoul(hapMatches[1].str()));
260 return true;
261 }
262 return false;
263 }
264
GetResourceId(const std::string & uri,std::string & path) const265 bool OhosFile::GetResourceId(const std::string& uri, std::string& path) const
266 {
267 std::smatch matches;
268 if (std::regex_match(uri, matches, MEDIA_HAP_RES_PATH_REGEX) && matches.size() == OHOS_RESOURCE_MATCH_SIZE) {
269 path = matches[1].str();
270 return true;
271 }
272 return false;
273 }
274
GetResourceName(const std::string & uri,std::string & resName) const275 bool OhosFile::GetResourceName(const std::string& uri, std::string& resName) const
276 {
277 std::smatch matches;
278 if (std::regex_match(uri, matches, MEDIA_RES_NAME_REGEX) && matches.size() == OHOS_RESOURCE_MATCH_SIZE) {
279 resName = matches[1].str();
280 return true;
281 }
282 return false;
283 }
284
OpenRawFile(BASE_NS::string_view uriIn,size_t & dataLen,std::unique_ptr<uint8_t[]> & dest)285 bool OhosFile::OpenRawFile(BASE_NS::string_view uriIn, size_t& dataLen, std::unique_ptr<uint8_t[]>& dest)
286 {
287 std::string uri(uriIn.data());
288 std::string rawFile;
289 if (GetResourceId(uri, rawFile)) {
290 auto state = fileResMgr_->GetResMgr()->GetRawFileFromHap(rawFile.c_str(), dataLen, dest);
291 if (state != OHOS::Global::Resource::SUCCESS || !dest) {
292 CORE_LOG_E("GetRawFileFromHap error, raw filename:%s, error:%u", rawFile.c_str(), state);
293 return false;
294 }
295 return true;
296 }
297 uint32_t resId = 0;
298 if (GetResourceId(uri, resId)) {
299 auto state = fileResMgr_->GetResMgr()->GetMediaDataById(resId, dataLen, dest);
300 if (state != OHOS::Global::Resource::SUCCESS || !dest) {
301 CORE_LOG_E("GetMediaDataById error, resId:%u, error:%u", resId, state);
302 return false;
303 }
304 return true;
305 }
306 std::string resName;
307 if (GetResourceName(uri, resName)) {
308 auto state = fileResMgr_->GetResMgr()->GetMediaDataByName(resName.c_str(), dataLen, dest);
309 if (state != OHOS::Global::Resource::SUCCESS || !dest) {
310 CORE_LOG_E("GetMediaDataByName error, resName:%s, error:%u", resName.c_str(), state);
311 return false;
312 }
313 return true;
314 }
315 CORE_LOG_E("load image data failed, as uri is invalid:%s", uri.c_str());
316 return false;
317 }
318 CORE_END_NAMESPACE()
319