• 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     const NativeResourceManager *resMgr;
66 
RawFileRawFile67     explicit RawFile(const std::string &path) : filePath(path), offset(0L), length(0L),
68         pf(nullptr), buffer(nullptr), resMgr{nullptr} {}
69 
~RawFileRawFile70     ~RawFile()
71     {
72         if (buffer != nullptr) {
73             free(buffer);
74             buffer = nullptr;
75         }
76         if (pf != nullptr) {
77             fclose(pf);
78             pf = nullptr;
79         }
80     }
81 
openRawFile82     bool open()
83     {
84         pf = std::fopen(filePath.c_str(), "rb");
85         return pf != nullptr;
86     }
87 };
88 
OH_ResourceManager_InitNativeResourceManager(napi_env env,napi_value jsResMgr)89 NativeResourceManager *OH_ResourceManager_InitNativeResourceManager(napi_env env, napi_value jsResMgr)
90 {
91     napi_valuetype valueType;
92     napi_typeof(env, jsResMgr, &valueType);
93     if (valueType != napi_object) {
94         HiLog::Error(LABEL, "jsResMgr is not an object");
95         return nullptr;
96     }
97     std::shared_ptr<ResourceManagerAddon> *addonPtr = nullptr;
98     napi_status status = napi_unwrap(env, jsResMgr, reinterpret_cast<void **>(&addonPtr));
99     if (status != napi_ok) {
100         HiLog::Error(LABEL, "Failed to get native resourcemanager");
101         return nullptr;
102     }
103     std::unique_ptr<NativeResourceManager> result = std::make_unique<NativeResourceManager>();
104     result->resManager = (*addonPtr)->GetResMgr();
105     return result.release();
106 }
107 
OH_ResourceManager_ReleaseNativeResourceManager(NativeResourceManager * resMgr)108 void OH_ResourceManager_ReleaseNativeResourceManager(NativeResourceManager *resMgr)
109 {
110     if (resMgr != nullptr) {
111         delete resMgr;
112         resMgr = nullptr;
113     }
114 }
115 
IsLoadHap(const NativeResourceManager * mgr,std::string & hapPath)116 static bool IsLoadHap(const NativeResourceManager *mgr, std::string &hapPath)
117 {
118     return mgr->resManager->IsLoadHap(hapPath) == RState::SUCCESS ? true : false;
119 }
120 
LoadRawDirFromHap(const NativeResourceManager * mgr,const std::string dirName)121 RawDir *LoadRawDirFromHap(const NativeResourceManager *mgr, const std::string dirName)
122 {
123     std::unique_ptr<RawDir> result = std::make_unique<RawDir>();
124     RState state = mgr->resManager->GetRawFileList(dirName, result->fileNameCache.names);
125     if (state != RState::SUCCESS) {
126         HiLog::Error(LABEL, "failed to get RawDir dirName, %{public}s", dirName.c_str());
127         return nullptr;
128     }
129     return result.release();
130 }
131 
OH_ResourceManager_OpenRawDir(const NativeResourceManager * mgr,const char * dirName)132 RawDir *OH_ResourceManager_OpenRawDir(const NativeResourceManager *mgr, const char *dirName)
133 {
134     if (mgr == nullptr || dirName == nullptr) {
135         return nullptr;
136     }
137     std::string hapPath;
138     if (IsLoadHap(mgr, hapPath)) {
139         return LoadRawDirFromHap(mgr, dirName);
140     }
141     ResourceManagerImpl* impl = static_cast<ResourceManagerImpl *>(mgr->resManager.get());
142     std::string tempName = dirName;
143     const std::string rawFileDirName = tempName.empty() ? "rawfile" : "rawfile/";
144     if (tempName.length() < rawFileDirName.length()
145         || (tempName.compare(0, rawFileDirName.length(), rawFileDirName) != 0)) {
146         tempName = rawFileDirName + tempName;
147     }
148     std::unique_ptr<RawDir> result = std::make_unique<RawDir>();
149     std::vector<std::string> resourcesPaths = impl->GetResourcePaths();
150     for (auto iter = resourcesPaths.begin(); iter != resourcesPaths.end(); iter++) {
151         std::string currentPath = *iter + tempName;
152         DIR* dir = opendir(currentPath.c_str());
153         if (dir == nullptr) {
154             continue;
155         }
156         struct dirent *dirp = readdir(dir);
157         while (dirp != nullptr) {
158             if (std::strcmp(dirp->d_name, ".") == 0 ||
159                 std::strcmp(dirp->d_name, "..") == 0) {
160                 dirp = readdir(dir);
161                 continue;
162             }
163             if (dirp->d_type == DT_REG || dirp->d_type == DT_DIR) {
164                 result->fileNameCache.names.push_back(tempName + "/" + dirp->d_name);
165             }
166 
167             dirp = readdir(dir);
168         }
169         closedir(dir);
170     }
171     return result.release();
172 }
173 
LoadRawFileFromHap(const NativeResourceManager * mgr,const char * fileName,const std::string hapPath)174 RawFile *LoadRawFileFromHap(const NativeResourceManager *mgr, const char *fileName, const std::string hapPath)
175 {
176     size_t len;
177     std::unique_ptr<uint8_t[]> tmpBuf;
178     RState state = mgr->resManager->GetRawFileFromHap(fileName, len, tmpBuf);
179     if (state != SUCCESS) {
180         HiLog::Error(LABEL, "failed to get %{public}s rawfile", fileName);
181         return nullptr;
182     }
183     auto result = std::make_unique<RawFile>(fileName);
184     result->buffer = reinterpret_cast<uint8_t*>(malloc(len));
185     if (result->buffer == nullptr) {
186         HiLog::Error(LABEL, "failed to malloc");
187         return nullptr;
188     }
189     int ret = memcpy_s(result->buffer, len, tmpBuf.get(), len);
190     if (ret != 0) {
191         HiLog::Error(LABEL, "failed to memcpy_s");
192         return nullptr;
193     }
194 
195     int zipFd = open(hapPath.c_str(), O_RDONLY);
196     if (zipFd < 0) {
197         HiLog::Error(LABEL, "failed open file %{public}s", hapPath.c_str());
198         return nullptr;
199     }
200     result->pf = fdopen(zipFd, "r");
201     result->length = static_cast<long>(len);
202     result->resMgr = mgr;
203     return result.release();
204 }
205 
OH_ResourceManager_OpenRawFile(const NativeResourceManager * mgr,const char * fileName)206 RawFile *OH_ResourceManager_OpenRawFile(const NativeResourceManager *mgr, const char *fileName)
207 {
208     if (mgr == nullptr || fileName == nullptr) {
209         return nullptr;
210     }
211 
212     std::string hapPath;
213     if (IsLoadHap(mgr, hapPath)) {
214         return LoadRawFileFromHap(mgr, fileName, hapPath);
215     }
216 
217     std::string filePath;
218     RState state = mgr->resManager->GetRawFilePathByName(fileName, filePath);
219     if (state != SUCCESS) {
220         return nullptr;
221     }
222     std::unique_ptr<RawFile> result = std::make_unique<RawFile>(filePath);
223     if (!result->open()) {
224         return nullptr;
225     }
226 
227     std::fseek(result->pf, 0, SEEK_END);
228     result->length = ftell(result->pf);
229     std::fseek(result->pf, 0, SEEK_SET);
230     return result.release();
231 }
232 
OH_ResourceManager_GetRawFileCount(RawDir * rawDir)233 int OH_ResourceManager_GetRawFileCount(RawDir *rawDir)
234 {
235     if (rawDir == nullptr) {
236         return 0;
237     }
238     return rawDir->fileNameCache.names.size();
239 }
240 
OH_ResourceManager_GetRawFileName(RawDir * rawDir,int index)241 const char *OH_ResourceManager_GetRawFileName(RawDir *rawDir, int index)
242 {
243     if (rawDir == nullptr || index < 0) {
244         return nullptr;
245     }
246     uint32_t rawFileCount = rawDir->fileNameCache.names.size();
247     if (rawFileCount == 0 || index >= static_cast<int>(rawFileCount)) {
248         return nullptr;
249     }
250     return rawDir->fileNameCache.names[index].c_str();
251 }
252 
OH_ResourceManager_CloseRawDir(RawDir * rawDir)253 void OH_ResourceManager_CloseRawDir(RawDir *rawDir)
254 {
255     if (rawDir != nullptr) {
256         delete rawDir;
257     }
258 }
259 
OH_ResourceManager_ReadRawFile(const RawFile * rawFile,void * buf,size_t length)260 int OH_ResourceManager_ReadRawFile(const RawFile *rawFile, void *buf, size_t length)
261 {
262     if (rawFile == nullptr || buf == nullptr || length == 0) {
263         return 0;
264     }
265     if (rawFile->buffer != nullptr) {
266         int ret = memcpy_s(buf, length, rawFile->buffer, rawFile->length);
267         if (ret != 0) {
268             HiLog::Error(LABEL, "failed to copy to buf");
269             return 0;
270         }
271         return rawFile->length;
272     } else {
273         return std::fread(buf, 1, length, rawFile->pf);
274     }
275 }
276 
OH_ResourceManager_SeekRawFile(const RawFile * rawFile,long offset,int whence)277 int OH_ResourceManager_SeekRawFile(const RawFile *rawFile, long offset, int whence)
278 {
279     if (rawFile == nullptr) {
280         return 0;
281     }
282 
283     int origin = 0;
284     int start = 0;
285     switch (whence) {
286         case SEEK_SET:
287             origin = SEEK_SET;
288             start = rawFile->offset + offset;
289             break;
290         case SEEK_CUR:
291             origin = SEEK_CUR;
292             start = offset;
293             break;
294         case SEEK_END:
295             start = rawFile->offset + rawFile->length + offset;
296             origin = SEEK_SET;
297             break;
298         default:
299             return -1;
300     }
301 
302     return std::fseek(rawFile->pf, start, origin);
303 }
304 
OH_ResourceManager_GetRawFileSize(RawFile * rawFile)305 long OH_ResourceManager_GetRawFileSize(RawFile *rawFile)
306 {
307     if (rawFile == nullptr) {
308         return 0;
309     }
310 
311     return rawFile->length;
312 }
313 
OH_ResourceManager_CloseRawFile(RawFile * rawFile)314 void OH_ResourceManager_CloseRawFile(RawFile *rawFile)
315 {
316     if (rawFile != nullptr) {
317         delete rawFile;
318     }
319 }
320 
OH_ResourceManager_GetRawFileOffset(const RawFile * rawFile)321 long OH_ResourceManager_GetRawFileOffset(const RawFile *rawFile)
322 {
323     if (rawFile == nullptr) {
324         return 0;
325     }
326     return ftell(rawFile->pf) - rawFile->offset;
327 }
328 
GetRawFileDescriptorFromHap(const RawFile * rawFile,RawFileDescriptor & descriptor)329 static bool GetRawFileDescriptorFromHap(const RawFile *rawFile, RawFileDescriptor &descriptor)
330 {
331     ResourceManager::RawFileDescriptor resMgrDescriptor;
332     int32_t ret = rawFile->resMgr->resManager->GetRawFileDescriptorFromHap(rawFile->filePath, resMgrDescriptor);
333     if (ret != 0) {
334         HiLog::Error(LABEL, "failed to get rawFile descriptor");
335         return false;
336     }
337     descriptor.fd = resMgrDescriptor.fd;
338     descriptor.length = resMgrDescriptor.length;
339     descriptor.start = resMgrDescriptor.offset;
340     return true;
341 }
342 
OH_ResourceManager_GetRawFileDescriptor(const RawFile * rawFile,RawFileDescriptor & descriptor)343 bool OH_ResourceManager_GetRawFileDescriptor(const RawFile *rawFile, RawFileDescriptor &descriptor)
344 {
345     if (rawFile == nullptr) {
346         return false;
347     }
348     if (rawFile->resMgr != nullptr) {
349         return GetRawFileDescriptorFromHap(rawFile, descriptor);
350     }
351     char paths[PATH_MAX] = {0};
352 #ifdef __WINNT__
353     if (!PathCanonicalizeA(paths, rawFile->filePath.c_str())) {
354         HiLog::Error(LABEL, "failed to PathCanonicalizeA the rawFile path");
355     }
356 #else
357     if (realpath(rawFile->filePath.c_str(), paths) == nullptr) {
358         HiLog::Error(LABEL, "failed to realpath the rawFile path");
359     }
360 #endif
361     int fd = open(paths, O_RDONLY);
362     if (fd > 0) {
363         descriptor.fd = fd;
364         descriptor.length = rawFile->length;
365         descriptor.start = rawFile->offset;
366     } else {
367         return false;
368     }
369     return true;
370 }
371 
OH_ResourceManager_ReleaseRawFileDescriptor(const RawFileDescriptor & descriptor)372 bool OH_ResourceManager_ReleaseRawFileDescriptor(const RawFileDescriptor &descriptor)
373 {
374     if (descriptor.fd > 0) {
375         return close(descriptor.fd) == 0;
376     }
377     return true;
378 }
379