• 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 "extractor.h"
17 
18 #include <fstream>
19 #include <sstream>
20 #include "ability_base_log_wrapper.h"
21 #include "constants.h"
22 #include "file_path_utils.h"
23 #include "hitrace_meter.h"
24 #include "securec.h"
25 #include "string_ex.h"
26 
27 namespace OHOS {
28 namespace AbilityBase {
29 namespace {
30 constexpr char EXT_NAME_ABC[] = ".abc";
31 }
Extractor(const std::string & source)32 Extractor::Extractor(const std::string &source) : zipFile_(source)
33 {
34     hapPath_ = source;
35 }
36 
~Extractor()37 Extractor::~Extractor()
38 {}
39 
Init()40 bool Extractor::Init()
41 {
42     if (initial_) {
43         ABILITYBASE_LOGD("already init");
44         return true;
45     }
46     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
47     if (!zipFile_.Open()) {
48         ABILITYBASE_LOGD("open zip file failed");
49         return false;
50     }
51     initial_ = true;
52     return true;
53 }
54 
GetFileBuffer(const std::string & srcPath,std::ostringstream & dest)55 bool Extractor::GetFileBuffer(const std::string& srcPath, std::ostringstream& dest)
56 {
57     std::unique_ptr<uint8_t[]> data;
58     size_t dataLen = 0;
59 
60     if (!ExtractToBufByName(srcPath, data, dataLen)) {
61         return false;
62     }
63 
64     dest.write(reinterpret_cast<char*>(data.get()), dataLen);
65     return true;
66 }
67 
GetFileList(const std::string & srcPath,std::vector<std::string> & assetList)68 bool Extractor::GetFileList(const std::string& srcPath, std::vector<std::string>& assetList)
69 {
70     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
71     if (!initial_) {
72         ABILITYBASE_LOGE("not init");
73         return false;
74     }
75 
76     if (srcPath.empty()) {
77         ABILITYBASE_LOGE("empty srcPath");
78         return false;
79     }
80     zipFile_.GetAllFileList(srcPath, assetList);
81     if (assetList.empty()) {
82         ABILITYBASE_LOGW("empty dir: %{public}s", srcPath.c_str());
83     }
84 
85     return true;
86 }
87 
HasEntry(const std::string & fileName) const88 bool Extractor::HasEntry(const std::string &fileName) const
89 {
90     if (!initial_) {
91         ABILITYBASE_LOGE("not init");
92         return false;
93     }
94 
95     return zipFile_.HasEntry(fileName);
96 }
97 
IsDirExist(const std::string & dir)98 bool Extractor::IsDirExist(const std::string &dir)
99 {
100     if (!initial_) {
101         ABILITYBASE_LOGE("not init");
102         return false;
103     }
104     if (dir.empty()) {
105         ABILITYBASE_LOGE("dir empty");
106         return false;
107     }
108     return zipFile_.IsDirExist(dir);
109 }
110 
ExtractByName(const std::string & fileName,std::ostream & dest) const111 bool Extractor::ExtractByName(const std::string &fileName, std::ostream &dest) const
112 {
113     std::unique_ptr<uint8_t[]> data;
114     size_t dataLen = 0;
115     if (!ExtractToBufByName(fileName, data, dataLen)) {
116         ABILITYBASE_LOGE("ExtractFile fail: %{public}s", fileName.c_str());
117         return false;
118     }
119     dest.write(reinterpret_cast<char*>(data.get()), dataLen);
120     return true;
121 }
122 
GetSpecifiedTypeFiles(std::vector<std::string> & fileNames,const std::string & suffix)123 void Extractor::GetSpecifiedTypeFiles(std::vector<std::string> &fileNames, const std::string &suffix)
124 {
125     auto &entryMap = zipFile_.GetAllEntries();
126     for (const auto &entry : entryMap) {
127         std::string fileName = entry.first;
128         auto position = fileName.rfind('.');
129         if (position != std::string::npos) {
130             std::string suffixStr = fileName.substr(position);
131             if (LowerStr(suffixStr) == suffix) {
132                 fileNames.emplace_back(fileName);
133             }
134         }
135     }
136 }
137 
GetData(const std::string & fileName) const138 std::unique_ptr<FileMapper> Extractor::GetData(const std::string &fileName) const
139 {
140     std::string relativePath = GetRelativePath(fileName);
141     return zipFile_.CreateFileMapper(relativePath, FileMapperType::NORMAL_MEM);
142 }
143 
GetSafeData(const std::string & fileName)144 std::shared_ptr<FileMapper> Extractor::GetSafeData(const std::string &fileName)
145 {
146     std::string relativePath = GetRelativePath(fileName);
147     if (!StringEndWith(relativePath, EXT_NAME_ABC, sizeof(EXT_NAME_ABC) - 1)) {
148         return nullptr;
149     }
150 
151     return zipFile_.CreateFileMapper(relativePath, FileMapperType::SAFE_ABC);
152 }
153 
GetMmapData(const std::string & fileName)154 std::unique_ptr<FileMapper> Extractor::GetMmapData(const std::string &fileName)
155 {
156     std::string relativePath = GetRelativePath(fileName);
157     return zipFile_.CreateFileMapper(relativePath, FileMapperType::SHARED_MMAP);
158 }
159 
UnzipData(std::unique_ptr<FileMapper> fileMapper,std::unique_ptr<uint8_t[]> & dataPtr,size_t & len) const160 bool Extractor::UnzipData(std::unique_ptr<FileMapper> fileMapper,
161     std::unique_ptr<uint8_t[]> &dataPtr, size_t &len) const
162 {
163     if (!initial_) {
164         ABILITYBASE_LOGE("not init");
165         return false;
166     }
167 
168     if (!fileMapper) {
169         ABILITYBASE_LOGE("null fileMapper");
170         return false;
171     }
172 
173     if (!zipFile_.ExtractFileFromMMap(fileMapper->GetFileName(), fileMapper->GetDataPtr(), dataPtr, len)) {
174         ABILITYBASE_LOGE("ExtractFileFromMMap failed");
175         return false;
176     }
177     return true;
178 }
179 
IsStageModel()180 bool Extractor::IsStageModel()
181 {
182     if (isStageModel_.has_value()) {
183         return isStageModel_.value();
184     }
185     isStageModel_ = !zipFile_.HasEntry("config.json");
186     return isStageModel_.value();
187 }
188 
ExtractToBufByName(const std::string & fileName,std::unique_ptr<uint8_t[]> & dataPtr,size_t & len) const189 bool Extractor::ExtractToBufByName(const std::string &fileName, std::unique_ptr<uint8_t[]> &dataPtr,
190     size_t &len) const
191 {
192     if (!initial_) {
193         ABILITYBASE_LOGW("not init");
194         return false;
195     }
196     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
197     std::string relativePath = GetRelativePath(fileName);
198     return zipFile_.ExtractToBufByName(relativePath, dataPtr, len);
199 }
200 
GetFileInfo(const std::string & fileName,FileInfo & fileInfo) const201 bool Extractor::GetFileInfo(const std::string &fileName, FileInfo &fileInfo) const
202 {
203     std::string relativePath = GetRelativePath(fileName);
204     ZipEntry zipEntry;
205     if (!zipFile_.GetEntry(relativePath, zipEntry)) {
206         ABILITYBASE_LOGE("Get entry failed");
207         return false;
208     }
209 
210     ZipPos offset = 0;
211     uint32_t length = 0;
212     if (!zipFile_.GetDataOffsetRelative(zipEntry, offset, length)) {
213         ABILITYBASE_LOGE("GetDataOffsetRelative failed");
214         return false;
215     }
216 
217     fileInfo.fileName = fileName;
218     fileInfo.offset = static_cast<uint32_t>(offset);
219     fileInfo.length = static_cast<uint32_t>(length);
220     fileInfo.lastModTime = zipEntry.modifiedTime;
221     fileInfo.lastModDate = zipEntry.modifiedDate;
222     return true;
223 }
224 
GetFileList(const std::string & srcPath,std::set<std::string> & fileSet)225 bool Extractor::GetFileList(const std::string &srcPath, std::set<std::string> &fileSet)
226 {
227     if (!initial_) {
228         ABILITYBASE_LOGE("not init");
229         return false;
230     }
231 
232     if (srcPath.empty()) {
233         ABILITYBASE_LOGE("empty srcPath");
234         return false;
235     }
236 
237     zipFile_.GetChildNames(srcPath, fileSet);
238     if (fileSet.empty()) {
239         ABILITYBASE_LOGD("empty dir: %{public}s", srcPath.c_str());
240     }
241 
242     return true;
243 }
244 
IsHapCompress(const std::string & fileName) const245 bool Extractor::IsHapCompress(const std::string &fileName) const
246 {
247     std::string relativePath = GetRelativePath(fileName);
248     ZipEntry zipEntry;
249     if (!zipFile_.GetEntry(relativePath, zipEntry)) {
250         ABILITYBASE_LOGE("GetEntry failed fileName: %{public}s", fileName.c_str());
251         return false;
252     }
253     return zipEntry.compressionMethod > 0;
254 }
255 
256 std::mutex ExtractorUtil::mapMutex_;
257 std::unordered_map<std::string, std::shared_ptr<Extractor>> ExtractorUtil::extractorMap_;
GetLoadFilePath(const std::string & hapPath)258 std::string ExtractorUtil::GetLoadFilePath(const std::string &hapPath)
259 {
260     std::string loadPath;
261     if (StringStartWith(hapPath, Constants::ABS_CODE_PATH, std::string(Constants::ABS_CODE_PATH).length())) {
262         loadPath = GetLoadPath(hapPath);
263     } else {
264         loadPath = hapPath;
265     }
266     return loadPath;
267 }
268 
GetExtractor(const std::string & hapPath,bool & newCreate,bool cache)269 std::shared_ptr<Extractor> ExtractorUtil::GetExtractor(const std::string &hapPath, bool &newCreate, bool cache)
270 {
271     newCreate = false;
272     if (hapPath.empty()) {
273         ABILITYBASE_LOGE("empty hapPath");
274         return nullptr;
275     }
276     {
277         HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, "GetExtractor_find_from_cache");
278         std::lock_guard<std::mutex> mapMutex(mapMutex_);
279         auto mapIter = extractorMap_.find(hapPath);
280         if (mapIter != extractorMap_.end()) {
281             ABILITYBASE_LOGD("hapPath: %{private}s", hapPath.c_str());
282             return mapIter->second;
283         }
284     }
285 
286     std::shared_ptr<Extractor> extractor = std::make_shared<Extractor>(hapPath);
287     if (!extractor->Init()) {
288         ABILITYBASE_LOGD("create failed for %{private}s", hapPath.c_str());
289         return nullptr;
290     }
291     if (cache) {
292         HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, "GetExtractor_store");
293         std::lock_guard<std::mutex> mapMutex(mapMutex_);
294         extractorMap_.emplace(hapPath, extractor);
295         ABILITYBASE_LOGD("extractor cache size: %{public}zu", extractorMap_.size());
296     }
297     newCreate = true;
298     return extractor;
299 }
300 
DeleteExtractor(const std::string & hapPath)301 void ExtractorUtil::DeleteExtractor(const std::string &hapPath)
302 {
303     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
304     if (hapPath.empty()) {
305         ABILITYBASE_LOGE("empty hapPath");
306         return;
307     }
308 
309     std::lock_guard<std::mutex> mapMutex(mapMutex_);
310     auto mapIter = extractorMap_.find(hapPath);
311     if (mapIter != extractorMap_.end()) {
312         ABILITYBASE_LOGI("hapPath: %{public}s", hapPath.c_str());
313         extractorMap_.erase(mapIter);
314     }
315 }
316 }  // namespace AbilityBase
317 }  // namespace OHOS
318