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 "raw_file_manager.h"
17
18 #include <cstdio>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22
23 #include "raw_dir.h"
24 #include "raw_file.h"
25 #include "resource_manager.h"
26 #include "resource_manager_addon.h"
27 #include "resource_manager_impl.h"
28 #include "hilog/log.h"
29
30 #ifdef __WINNT__
31 #include <shlwapi.h>
32 #include <windows.h>
33 #else
34 #include <dlfcn.h>
35 #endif
36
37 using namespace OHOS::Global::Resource;
38 using namespace OHOS::HiviewDFX;
39
40 namespace {
41 constexpr HiLogLabel LABEL = {LOG_CORE, 0xD001E00, "RawFile"};
42 }
43
44 struct NativeResourceManager {
45 std::shared_ptr<ResourceManager> resManager = nullptr;
46 };
47
48 struct FileNameCache {
49 int maxCount = 0;
50 std::vector<std::string> names;
51 };
52
53 struct RawDir {
54 std::shared_ptr<ResourceManager> resManager = nullptr;
55 struct FileNameCache fileNameCache;
56 };
57
58 struct RawFile {
59 const std::string filePath;
60 long offset;
61 long length;
62 FILE* pf;
63
RawFileRawFile64 explicit RawFile(const std::string &path) : filePath(path), offset(0L), length(0L), pf(nullptr) {}
65
~RawFileRawFile66 ~RawFile()
67 {
68 if (pf != nullptr) {
69 fclose(pf);
70 pf = nullptr;
71 }
72 }
73
openRawFile74 bool open()
75 {
76 pf = std::fopen(filePath.c_str(), "rb");
77 return pf != nullptr;
78 }
79 };
80
OH_ResourceManager_InitNativeResourceManager(napi_env env,napi_value jsResMgr)81 NativeResourceManager *OH_ResourceManager_InitNativeResourceManager(napi_env env, napi_value jsResMgr)
82 {
83 napi_valuetype valueType;
84 napi_typeof(env, jsResMgr, &valueType);
85 if (valueType != napi_object) {
86 HiLog::Error(LABEL, "jsResMgr is not an object");
87 return nullptr;
88 }
89 std::shared_ptr<ResourceManagerAddon> *addonPtr = nullptr;
90 napi_status status = napi_unwrap(env, jsResMgr, reinterpret_cast<void **>(&addonPtr));
91 if (status != napi_ok) {
92 HiLog::Error(LABEL, "Failed to get native resourcemanager");
93 return nullptr;
94 }
95 std::unique_ptr<NativeResourceManager> result = std::make_unique<NativeResourceManager>();
96 result->resManager = (*addonPtr)->GetResMgr();
97 return result.release();
98 }
99
OH_ResourceManager_ReleaseNativeResourceManager(NativeResourceManager * resMgr)100 void OH_ResourceManager_ReleaseNativeResourceManager(NativeResourceManager *resMgr)
101 {
102 if (resMgr != nullptr) {
103 delete resMgr;
104 }
105 }
106
OH_ResourceManager_OpenRawDir(const NativeResourceManager * mgr,const char * dirName)107 RawDir *OH_ResourceManager_OpenRawDir(const NativeResourceManager *mgr, const char *dirName)
108 {
109 if (mgr == nullptr || dirName == nullptr) {
110 return nullptr;
111 }
112 ResourceManagerImpl* impl = static_cast<ResourceManagerImpl *>(mgr->resManager.get());
113 std::string tempName = dirName;
114 const std::string rawFileDirName = "rawfile/";
115 if (tempName.length() < rawFileDirName.length()
116 || (tempName.compare(0, rawFileDirName.length(), rawFileDirName) != 0)) {
117 tempName = rawFileDirName + tempName;
118 }
119 std::unique_ptr<RawDir> result = std::make_unique<RawDir>();
120 std::vector<std::string> resourcesPaths = impl->GetResourcePaths();
121 for (auto iter = resourcesPaths.begin(); iter != resourcesPaths.end(); iter++) {
122 std::string currentPath = *iter + tempName;
123 DIR* dir = opendir(currentPath.c_str());
124 if (dir == nullptr) {
125 continue;
126 }
127 struct dirent *dirp = readdir(dir);
128 while (dirp != nullptr) {
129 if (std::strcmp(dirp->d_name, ".") == 0 ||
130 std::strcmp(dirp->d_name, "..") == 0) {
131 dirp = readdir(dir);
132 continue;
133 }
134 if (dirp->d_type == DT_REG) {
135 result->fileNameCache.names.push_back(tempName + "/" + dirp->d_name);
136 }
137
138 dirp = readdir(dir);
139 }
140 closedir(dir);
141 }
142 return result.release();
143 }
144
OH_ResourceManager_OpenRawFile(const NativeResourceManager * mgr,const char * fileName)145 RawFile *OH_ResourceManager_OpenRawFile(const NativeResourceManager *mgr, const char *fileName)
146 {
147 if (mgr == nullptr || fileName == nullptr) {
148 return nullptr;
149 }
150
151 std::string filePath;
152 RState state = mgr->resManager->GetRawFilePathByName(fileName, filePath);
153 if (state != SUCCESS) {
154 return nullptr;
155 }
156 std::unique_ptr<RawFile> result = std::make_unique<RawFile>(filePath);
157 if (!result->open()) {
158 return nullptr;
159 }
160
161 std::fseek(result->pf, 0, SEEK_END);
162 result->length = ftell(result->pf);
163 std::fseek(result->pf, 0, SEEK_SET);
164 return result.release();
165 }
166
OH_ResourceManager_GetRawFileCount(RawDir * rawDir)167 int OH_ResourceManager_GetRawFileCount(RawDir *rawDir)
168 {
169 if (rawDir == nullptr) {
170 return 0;
171 }
172 return rawDir->fileNameCache.names.size();
173 }
174
OH_ResourceManager_GetRawFileName(RawDir * rawDir,int index)175 const char *OH_ResourceManager_GetRawFileName(RawDir *rawDir, int index)
176 {
177 if (rawDir == nullptr || index < 0) {
178 return nullptr;
179 }
180 uint32_t rawFileCount = rawDir->fileNameCache.names.size();
181 if (rawFileCount == 0 || index >= static_cast<int>(rawFileCount)) {
182 return nullptr;
183 }
184 return rawDir->fileNameCache.names[index].c_str();
185 }
186
OH_ResourceManager_CloseRawDir(RawDir * rawDir)187 void OH_ResourceManager_CloseRawDir(RawDir *rawDir)
188 {
189 if (rawDir != nullptr) {
190 delete rawDir;
191 }
192 }
193
OH_ResourceManager_ReadRawFile(const RawFile * rawFile,void * buf,size_t length)194 int OH_ResourceManager_ReadRawFile(const RawFile *rawFile, void *buf, size_t length)
195 {
196 if (rawFile == nullptr || buf == nullptr || length == 0) {
197 return 0;
198 }
199 return std::fread(buf, 1, length, rawFile->pf);
200 }
201
OH_ResourceManager_SeekRawFile(const RawFile * rawFile,long offset,int whence)202 int OH_ResourceManager_SeekRawFile(const RawFile *rawFile, long offset, int whence)
203 {
204 if (rawFile == nullptr) {
205 return 0;
206 }
207
208 int origin = 0;
209 int start = 0;
210 switch (whence) {
211 case SEEK_SET:
212 origin = SEEK_SET;
213 start = rawFile->offset + offset;
214 break;
215 case SEEK_CUR:
216 origin = SEEK_CUR;
217 start = offset;
218 break;
219 case SEEK_END:
220 start = rawFile->offset + rawFile->length + offset;
221 origin = SEEK_SET;
222 break;
223 default:
224 return -1;
225 }
226
227 return std::fseek(rawFile->pf, start, origin);
228 }
229
OH_ResourceManager_GetRawFileSize(RawFile * rawFile)230 long OH_ResourceManager_GetRawFileSize(RawFile *rawFile)
231 {
232 if (rawFile == nullptr) {
233 return 0;
234 }
235
236 return rawFile->length;
237 }
238
OH_ResourceManager_CloseRawFile(RawFile * rawFile)239 void OH_ResourceManager_CloseRawFile(RawFile *rawFile)
240 {
241 if (rawFile != nullptr) {
242 delete rawFile;
243 }
244 }
245
OH_ResourceManager_GetRawFileOffset(const RawFile * rawFile)246 long OH_ResourceManager_GetRawFileOffset(const RawFile *rawFile)
247 {
248 if (rawFile == nullptr) {
249 return 0;
250 }
251 return ftell(rawFile->pf) - rawFile->offset;
252 }
253
OH_ResourceManager_GetRawFileDescriptor(const RawFile * rawFile,RawFileDescriptor & descriptor)254 bool OH_ResourceManager_GetRawFileDescriptor(const RawFile *rawFile, RawFileDescriptor &descriptor)
255 {
256 if (rawFile == nullptr) {
257 return false;
258 }
259 char paths[PATH_MAX] = {0};
260 #ifdef __WINNT__
261 if (!PathCanonicalizeA(paths, rawFile->filePath.c_str())) {
262 HiLog::Error(LABEL, "failed to PathCanonicalizeA the rawFile path");
263 }
264 #else
265 if (realpath(rawFile->filePath.c_str(), paths) == nullptr) {
266 HiLog::Error(LABEL, "failed to realpath the rawFile path");
267 }
268 #endif
269 int fd = open(paths, O_RDONLY);
270 if (fd > 0) {
271 descriptor.fd = fd;
272 descriptor.length = rawFile->length;
273 descriptor.start = rawFile->offset;
274 } else {
275 return false;
276 }
277 return true;
278 }
279
OH_ResourceManager_ReleaseRawFileDescriptor(const RawFileDescriptor & descriptor)280 bool OH_ResourceManager_ReleaseRawFileDescriptor(const RawFileDescriptor &descriptor)
281 {
282 if (descriptor.fd > 0) {
283 return close(descriptor.fd) == 0;
284 }
285 return true;
286 }
287