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