1 /*
2 * Copyright (c) 2022 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 <cerrno>
19 #include <cstdint>
20 #include <dirent.h>
21
22 #ifndef _DIRENT_HAVE_D_TYPE
23 #include <sys/stat.h>
24 #include <sys/types.h>
25
26 #endif
27 #include <climits>
28 #define CORE_MAX_PATH PATH_MAX
29
30 #include <base/containers/string.h>
31 #include <base/containers/string_view.h>
32 #include <core/io/intf_file.h>
33 #include <core/log.h>
34 #include <core/namespace.h>
35
36 #include "io/std_directory.h"
37
38 CORE_BEGIN_NAMESPACE()
39 using BASE_NS::CloneData;
40 using BASE_NS::string;
41 using BASE_NS::string_view;
42
43 const std::regex MEDIA_RES_ID_REGEX(R"(^\w+/([0-9]+)\.\w+$)", std::regex::icase);
44 const std::regex MEDIA_HAP_RES_PATH_REGEX(R"(^(.*)$)");
45 const std::regex MEDIA_HAP_RES_ID_REGEX(R"(^.*/([0-9]+)\.\w+$)", std::regex::icase);
46 const std::regex MEDIA_RES_NAME_REGEX(R"(^.*/(\w+)\.\w+$)", std::regex::icase);
47
48 constexpr uint32_t OHOS_RESOURCE_MATCH_SIZE = 2;
49
UpdateResManager(const PlatformHapInfo & hapInfo)50 void OhosResMgr::UpdateResManager(const PlatformHapInfo& hapInfo)
51 {
52 auto key = hapInfo.bundleName + "+" + hapInfo.moduleName;
53 auto resourceMgrIter = resourceManagers_.find(key);
54 if (resourceMgrIter != resourceManagers_.end()) {
55 resourceManager_ = resourceMgrIter->second;
56 return;
57 }
58
59 if (hapInfo.resourceManager != nullptr) {
60 resourceManagers_[key] = hapInfo.resourceManager;
61 resourceManager_ = hapInfo.resourceManager;
62 CORE_LOG_D("resource manager has ready by new api");
63 return;
64 }
65
66 std::shared_ptr<OHOS::Global::Resource::ResourceManager> newResMgr(OHOS::Global::Resource::CreateResourceManager());
67 if (!newResMgr) {
68 CORE_LOG_E("CreateResourceManager failed");
69 return;
70 }
71 auto resRet = newResMgr->AddResource(hapInfo.hapPath.c_str());
72 resourceManagers_[key] = newResMgr;
73 resourceManager_ = newResMgr;
74 }
75
GetResMgr() const76 std::shared_ptr<OHOS::Global::Resource::ResourceManager> OhosResMgr::GetResMgr() const
77 {
78 return resourceManager_;
79 }
80
OhosFileDirectory(BASE_NS::refcnt_ptr<OhosResMgr> resMgr)81 OhosFileDirectory::OhosFileDirectory(BASE_NS::refcnt_ptr<OhosResMgr> resMgr) : dirResMgr_(resMgr) {}
82
~OhosFileDirectory()83 OhosFileDirectory::~OhosFileDirectory()
84 {
85 Close();
86 }
87
Close()88 void OhosFileDirectory::Close()
89 {
90 if (dir_) {
91 dir_.reset();
92 }
93 }
94
IsDir(BASE_NS::string_view path,std::vector<std::string> & fileList) const95 bool OhosFileDirectory::IsDir(BASE_NS::string_view path, std::vector<std::string>& fileList) const
96 {
97 auto state = dirResMgr_->GetResMgr()->GetRawFileList(path.data(), fileList);
98 if (state != OHOS::Global::Resource::SUCCESS || fileList.empty()) {
99 CORE_LOG_E("GetRawfilepath error, filename:%s, error:%u", path.data(), state);
100 return false;
101 }
102 return true;
103 }
104
IsFile(BASE_NS::string_view path) const105 bool OhosFileDirectory::IsFile(BASE_NS::string_view path) const
106 {
107 std::unique_ptr<uint8_t[]> data;
108 size_t dataLen = 0;
109 auto state = dirResMgr_->GetResMgr()->GetRawFileFromHap(path.data(), dataLen, data);
110 if (state != OHOS::Global::Resource::SUCCESS) {
111 return false;
112 }
113 return true;
114 }
115
Open(const BASE_NS::string_view pathIn)116 bool OhosFileDirectory::Open(const BASE_NS::string_view pathIn)
117 {
118 auto path = pathIn;
119 if (path.back() == '/') {
120 path.remove_suffix(1);
121 }
122 if (path.front() == '/') {
123 path.remove_prefix(1);
124 }
125 std::vector<std::string> fileList;
126 if (IsDir(path, fileList)) {
127 dir_ = BASE_NS::make_unique<OhosDirImpl>(path, fileList);
128 return true;
129 }
130 return false;
131 }
132
GetEntries() const133 BASE_NS::vector<IDirectory::Entry> OhosFileDirectory::GetEntries() const
134 {
135 CORE_ASSERT_MSG(dir_, "Dir not open");
136 BASE_NS::vector<IDirectory::Entry> result;
137 if (dir_) {
138 for (int i = 0; i < static_cast<int>(dir_->fileList_.size()); i++) {
139 auto path = dir_->path_ + "/" + BASE_NS::string(dir_->fileList_[i].c_str());
140 auto entry = GetEntry(path);
141 entry.timestamp = static_cast<uint32_t>(i);
142 entry.name = dir_->fileList_[i].c_str();
143 result.emplace_back(entry);
144 }
145 }
146 return result;
147 }
148
GetEntry(BASE_NS::string_view uriIn) const149 IDirectory::Entry OhosFileDirectory::GetEntry(BASE_NS::string_view uriIn) const
150 {
151 if (!uriIn.empty()) {
152 IDirectory::Entry::Type type;
153 std::vector<std::string> fileList;
154 if (IsFile(uriIn)) {
155 type = IDirectory::Entry::FILE;
156 } else if (IsDir(uriIn, fileList)) {
157 type = IDirectory::Entry::DIRECTORY;
158 } else {
159 type = IDirectory::Entry::UNKNOWN;
160 }
161 // timestamp set 0
162 uint64_t timestamp = 0;
163 BASE_NS::string entryName { uriIn };
164 return IDirectory::Entry { type, entryName, timestamp };
165 }
166 return {};
167 }
168
OhosFile(BASE_NS::refcnt_ptr<OhosResMgr> resMgr)169 OhosFile::OhosFile(BASE_NS::refcnt_ptr<OhosResMgr> resMgr) : fileResMgr_(resMgr)
170 {
171 buffer_ = std::make_shared<OhosFileStorage>(nullptr);
172 }
173
UpdateStorage(std::shared_ptr<OhosFileStorage> buffer)174 void OhosFile::UpdateStorage(std::shared_ptr<OhosFileStorage> buffer)
175 {
176 buffer_ = BASE_NS::move(buffer);
177 }
178
GetMode() const179 IFile::Mode OhosFile::GetMode() const
180 {
181 return IFile::Mode::READ_ONLY;
182 }
183
Close()184 void OhosFile::Close() {}
185
Read(void * buffer,uint64_t count)186 uint64_t OhosFile::Read(void* buffer, uint64_t count)
187 {
188 uint64_t toRead = count;
189 uint64_t sum = index_ + toRead;
190 if (sum < index_) {
191 return 0;
192 }
193 if (sum > buffer_->Size()) {
194 toRead = buffer_->Size() - index_;
195 }
196 if (toRead <= 0) {
197 return toRead;
198 }
199 if (toRead > SIZE_MAX) {
200 CORE_ASSERT_MSG(false, "Unable to read chunks bigger than (SIZE_MAX) bytes.");
201 return 0;
202 }
203 if (CloneData(buffer, static_cast<size_t>(count), &(buffer_->GetStorage()[index_]), static_cast<size_t>(toRead))) {
204 index_ += toRead;
205 }
206 return toRead;
207 }
208
Write(const void * buffer,uint64_t count)209 uint64_t OhosFile::Write(const void* buffer, uint64_t count)
210 {
211 return 0;
212 }
213
Append(const void * buffer,uint64_t count,uint64_t flushSize)214 uint64_t OhosFile::Append(const void* buffer, uint64_t count, uint64_t flushSize)
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