1 /*
2 * Copyright (c) 2024 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 "unzip_wrapper.h"
17
18 #include <fstream>
19 #include <iostream>
20
21 #include "log.h"
22 #include "utils.h"
23
24 namespace OHOS {
25 namespace AppPackingTool {
UnzipWrapper()26 UnzipWrapper::UnzipWrapper()
27 {}
28
UnzipWrapper(std::string path)29 UnzipWrapper::UnzipWrapper(std::string path) : unzFilePath_(path)
30 {}
31
~UnzipWrapper()32 UnzipWrapper::~UnzipWrapper()
33 {
34 Close();
35 }
36
Open(std::string & unzPath)37 int32_t UnzipWrapper::Open(std::string& unzPath)
38 {
39 unzFilePath_ = unzPath;
40 return Open();
41 }
42
Open()43 int32_t UnzipWrapper::Open()
44 {
45 if (unzFile_ != nullptr) {
46 LOGE("unzip file handle has open");
47 return ZIP_ERR_SUCCESS;
48 }
49 unzFile_ = unzOpen64(unzFilePath_.c_str());
50 if (unzFile_ == nullptr) {
51 LOGE("unzip file handle open failed");
52 return ZIP_ERR_FAILURE;
53 }
54 return ZIP_ERR_SUCCESS;
55 }
56
Close()57 void UnzipWrapper::Close()
58 {
59 if (unzFile_ != nullptr) {
60 unzClose(unzFile_);
61 unzFile_ = nullptr;
62 }
63 }
64
ExtractFile(const std::string filePath)65 std::string UnzipWrapper::ExtractFile(const std::string filePath)
66 {
67 char filename[MAX_ZIP_BUFFER_SIZE] = {0};
68 unz_file_info64 fileInfo;
69 if (unzGetCurrentFileInfo64(unzFile_, &fileInfo, filename, MAX_ZIP_BUFFER_SIZE, NULL, 0, NULL, 0) != UNZ_OK) {
70 LOGE("get current file info in zip failed!");
71 return "";
72 }
73 fs::path fsUnzipPath(filename);
74 fs::path fsFilePath(filePath);
75 fs::path fsFullFilePath = fsFilePath / filename;
76 if (fileInfo.external_fa == ZIP_FILE_ATTR_DIRECTORY ||
77 (fsUnzipPath.string().rfind('/') == fsUnzipPath.string().length() - 1)) {
78 if (!fs::exists(fsFullFilePath)) {
79 fs::create_directories(fsFullFilePath.string());
80 }
81 return fsFullFilePath.string();
82 }
83 if (!fs::exists(fsFullFilePath.parent_path())) {
84 fs::create_directories(fsFullFilePath.parent_path().string());
85 }
86 if (unzOpenCurrentFile(unzFile_) != UNZ_OK) {
87 LOGE("open current file in zip failed![filename=%s]", filename);
88 return "";
89 }
90 std::string realFullFilePath;
91 if (!Utils::GetRealPathOfNoneExistFile(fsFullFilePath.string(), realFullFilePath)) {
92 LOGE("get real full file path failed! jsonFile=%s", fsFullFilePath.string().c_str());
93 return "";
94 }
95 std::fstream file(realFullFilePath, std::ios_base::out | std::ios_base::binary);
96 if (!file.is_open()) {
97 LOGE("open file failed![fsFullFilePath=%s]", fsFullFilePath.string().c_str());
98 return "";
99 }
100 char fileData[MAX_ZIP_BUFFER_SIZE] = {0};
101 int32_t bytesRead;
102 do {
103 bytesRead = unzReadCurrentFile(unzFile_, (voidp)fileData, MAX_ZIP_BUFFER_SIZE);
104 if (bytesRead < 0) {
105 LOGE("Read current file in zip failed!!");
106 file.close();
107 return "";
108 }
109 file.write(fileData, bytesRead);
110 } while (bytesRead > 0);
111 file.close();
112 unzCloseCurrentFile(unzFile_);
113 return realFullFilePath;
114 }
115
UnzipFile(std::string filePath)116 int32_t UnzipWrapper::UnzipFile(std::string filePath)
117 {
118 LOGD("Unzip file[%s] to [%s]", unzFilePath_.c_str(), filePath.c_str());
119 if (unzFile_ == nullptr) {
120 LOGE("zip file not open");
121 return ZIP_ERR_FAILURE;
122 }
123 if (unzGetGlobalInfo64(unzFile_, &unzGlobalInfo_) != UNZ_OK) {
124 LOGE("Get global info failed!");
125 return ZIP_ERR_FAILURE;
126 }
127 int ret = UNZ_OK;
128 for (size_t i = 0; i < unzGlobalInfo_.number_entry; ++i) {
129 std::string f = ExtractFile(filePath);
130 if (f.empty()) {
131 LOGE("Extract file failed!");
132 return ZIP_ERR_FAILURE;
133 }
134 ret = unzGoToNextFile(unzFile_);
135 if (ret == UNZ_END_OF_LIST_OF_FILE) {
136 break;
137 } else if (ret != UNZ_OK) {
138 LOGE("Go to next file in zip failed!");
139 return ZIP_ERR_FAILURE;
140 }
141 }
142 return ZIP_ERR_SUCCESS;
143 }
144 } // namespace AppPackingTool
145 } // namespace OHOS
146