• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #include "util/zip/zip_writer.h"
16 #include <chrono>
17 #include "directory_ex.h"
18 #include "dump_utils.h"
19 #include "hilog_wrapper.h"
20 namespace OHOS {
21 namespace HiviewDFX {
22 namespace {
23 static const int PROCENT100 = 100;
24 static const int kZipBufSize = 8192;
25 static const int kBaseYear = 1900;
26 static const uLong LANGUAGE_ENCODING_FLAG = 0x1 << 11;
27 } // namespace
28 
ZipWriter(const std::string & zipFilePath)29 ZipWriter::ZipWriter(const std::string &zipFilePath) : zipFilePath_(zipFilePath), zipFile_(nullptr)
30 {
31     DUMPER_HILOGD(MODULE_COMMON, "create|zipFilePath=[%{public}s]", zipFilePath_.c_str());
32 }
33 
~ZipWriter()34 ZipWriter::~ZipWriter()
35 {
36     DUMPER_HILOGD(MODULE_COMMON, "release|");
37     zipItems_.clear();
38     Close();
39 }
40 
Open()41 bool ZipWriter::Open()
42 {
43     DUMPER_HILOGD(MODULE_COMMON, "Open enter|zipFilePath=[%{public}s]", zipFilePath_.c_str());
44 
45     if (zipFilePath_.empty()) {
46         DUMPER_HILOGD(MODULE_COMMON, "Open leave|false, path is empty");
47         return false;
48     }
49 
50     DUMPER_HILOGD(MODULE_COMMON, "Open debug|");
51     zipFile_ = OpenForZipping(zipFilePath_, APPEND_STATUS_CREATE);
52     if (zipFile_ == nullptr) {
53         DUMPER_HILOGD(MODULE_COMMON, "Open leave|false, couldn't create ZIP file");
54         return false;
55     }
56 
57     DUMPER_HILOGD(MODULE_COMMON, "Open leave|true, create ZIP file");
58     return true;
59 }
60 
Close()61 bool ZipWriter::Close()
62 {
63     DUMPER_HILOGD(MODULE_COMMON, "Close enter|");
64 
65     int res = ZIP_OK;
66 
67     if (zipFile_ != nullptr) {
68         res = zipClose(zipFile_, nullptr);
69     }
70     zipFile_ = nullptr;
71 
72     bool ret = (res == ZIP_OK);
73 
74     DUMPER_HILOGD(MODULE_COMMON, "Close leave|ret=%{public}d, res=%{public}d", ret, res);
75     return ret;
76 }
77 
Write(const std::vector<std::pair<std::string,std::string>> & zipItems,const ZipTickNotify notify)78 bool ZipWriter::Write(const std::vector<std::pair<std::string, std::string>> &zipItems, const ZipTickNotify notify)
79 {
80     DUMPER_HILOGD(MODULE_COMMON, "Write enter|");
81 
82     if (zipFile_ == nullptr) {
83         return false;
84     }
85 
86     zipItems_.insert(zipItems_.end(), zipItems.begin(), zipItems.end());
87 
88     bool ret = FlushItems(notify);
89     DUMPER_HILOGD(MODULE_COMMON, "Write debug|FlushItems, ret=%{public}d", ret);
90 
91     if (ret) {
92         ret = Close();
93     }
94 
95     DUMPER_HILOGD(MODULE_COMMON, "Write leave|ret=%{public}d", ret);
96     return ret;
97 }
98 
FlushItems(const ZipTickNotify notify)99 bool ZipWriter::FlushItems(const ZipTickNotify notify)
100 {
101     DUMPER_HILOGD(MODULE_COMMON, "FlushItems enter|");
102 
103     std::vector<std::pair<std::string, std::string>> zipItems;
104     zipItems.assign(zipItems_.begin(), zipItems_.end());
105     zipItems_.clear();
106 
107     bool ret = true;
108     for (size_t i = 0; i < zipItems.size(); i++) {
109         if ((notify != nullptr) && (notify(((PROCENT100 * i) / zipItems.size()), UNSET_PROGRESS))) {
110             DUMPER_HILOGE(MODULE_COMMON, "FlushItems error|notify");
111             ret = false;
112             break;
113         }
114 
115         auto item = zipItems[i];
116         std::string absolutePath = item.first; // first:absolutePath
117         std::string relativePath = item.second; // second:relativePath
118         DUMPER_HILOGD(MODULE_COMMON, "FlushItems debug|relativePath=[%{public}s], absolutePath=[%{public}s]",
119             relativePath.c_str(), absolutePath.c_str());
120 
121         if (!AddFileEntryToZip(zipFile_, relativePath, absolutePath)) {
122             DUMPER_HILOGE(MODULE_COMMON, "FlushItems error|false, failed to write file");
123             ret = false;
124             break;
125         }
126     }
127 
128     DUMPER_HILOGD(MODULE_COMMON, "FlushItems leave|ret=%{public}d", ret);
129     return ret;
130 }
131 
SetTimeToZipFileInfo(zip_fileinfo & zipInfo)132 bool ZipWriter::SetTimeToZipFileInfo(zip_fileinfo &zipInfo)
133 {
134     auto nowTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
135     struct tm localTime = {0};
136     if (localtime_r(&nowTime, &localTime) == nullptr) {
137         DUMPER_HILOGE(MODULE_COMMON, "SetTimeToZipFileInfo error|nullptr");
138         return false;
139     }
140 
141     zipInfo.tmz_date.tm_year = static_cast<uInt>(localTime.tm_year + kBaseYear);
142     zipInfo.tmz_date.tm_mon = static_cast<uInt>(localTime.tm_mon);
143     zipInfo.tmz_date.tm_mday = static_cast<uInt>(localTime.tm_mday);
144     zipInfo.tmz_date.tm_hour = static_cast<uInt>(localTime.tm_hour);
145     zipInfo.tmz_date.tm_min = static_cast<uInt>(localTime.tm_min);
146     zipInfo.tmz_date.tm_sec = static_cast<uInt>(localTime.tm_sec);
147     return true;
148 }
149 
OpenForZipping(const std::string & fileName,int append)150 zipFile ZipWriter::OpenForZipping(const std::string &fileName, int append)
151 {
152     return zipOpen2(fileName.c_str(), append, nullptr, nullptr);
153 }
154 
ZipOpenNewFileInZip(zipFile zip_file,const std::string & strPath)155 bool ZipWriter::ZipOpenNewFileInZip(zipFile zip_file, const std::string &strPath)
156 {
157     DUMPER_HILOGD(MODULE_COMMON, "ZipOpenNewFileInZip enter|strPath=[%{public}s]", strPath.c_str());
158 
159     zip_fileinfo fileInfo = {};
160     SetTimeToZipFileInfo(fileInfo);
161 
162     int res = zipOpenNewFileInZip4(zip_file, strPath.c_str(), &fileInfo,
163         nullptr, 0u, nullptr, 0u, nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION,
164         0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, nullptr, 0, 0, LANGUAGE_ENCODING_FLAG);
165 
166     bool ret = (res == ZIP_OK);
167 
168     DUMPER_HILOGD(MODULE_COMMON, "ZipOpenNewFileInZip leave|ret=%{public}d, res=%{public}d", ret, res);
169     return ret;
170 }
171 
AddFileContentToZip(zipFile zip_file,std::string & file_path)172 bool ZipWriter::AddFileContentToZip(zipFile zip_file, std::string &file_path)
173 {
174     DUMPER_HILOGD(MODULE_COMMON, "AddFileContentToZip enter|file_path=[%{public}s]", file_path.c_str());
175 
176     if (!DumpUtils::PathIsValid(file_path)) {
177         DUMPER_HILOGE(MODULE_COMMON, "AddFileContentToZip leave|false, PathIsValid");
178         return false;
179     }
180 
181     auto fp = fopen(file_path.c_str(), "rb");
182     if (fp == nullptr) {
183         DUMPER_HILOGE(MODULE_COMMON, "AddFileContentToZip leave|false, fopen");
184         return false;
185     }
186 
187     bool ret = true;
188     char buf[kZipBufSize];
189     while (!feof(fp)) {
190         size_t readSum = fread(buf, 1, kZipBufSize, fp);
191         if (readSum < 1) {
192             continue;
193         }
194 
195         if (zipWriteInFileInZip(zip_file, buf, readSum) != ZIP_OK) {
196             DUMPER_HILOGE(MODULE_COMMON, "AddFileContentToZip error|could not write data to zip");
197             ret = false;
198             break;
199         }
200     }
201 
202     (void)fclose(fp);
203     fp = nullptr;
204 
205     DUMPER_HILOGD(MODULE_COMMON, "AddFileContentToZip leave|ret=%{public}d", ret);
206     return ret;
207 }
208 
OpenNewFileEntry(zipFile zip_file,std::string & path)209 bool ZipWriter::OpenNewFileEntry(zipFile zip_file, std::string &path)
210 {
211     DUMPER_HILOGD(MODULE_COMMON, "OpenNewFileEntry enter|path=[%{public}s]", path.c_str());
212 
213     bool ret = ZipOpenNewFileInZip(zip_file, path);
214 
215     DUMPER_HILOGD(MODULE_COMMON, "OpenNewFileEntry leave|ret=%{public}d", ret);
216     return ret;
217 }
218 
CloseNewFileEntry(zipFile zip_file)219 bool ZipWriter::CloseNewFileEntry(zipFile zip_file)
220 {
221     DUMPER_HILOGD(MODULE_COMMON, "CloseNewFileEntry enter|");
222 
223     int res = zipCloseFileInZip(zip_file);
224     bool ret = (res == ZIP_OK);
225 
226     DUMPER_HILOGD(MODULE_COMMON, "CloseNewFileEntry leave|ret=%{public}d, res=%{public}d", ret, res);
227     return ret;
228 }
229 
AddFileEntryToZip(zipFile zip_file,std::string & relativePath,std::string & absolutePath)230 bool ZipWriter::AddFileEntryToZip(zipFile zip_file, std::string &relativePath, std::string &absolutePath)
231 {
232     DUMPER_HILOGD(MODULE_COMMON, "AddFileEntryToZip enter|relativePath=[%{public}s], absolutePath=[%{public}s]",
233         relativePath.c_str(), absolutePath.c_str());
234 
235     if (!OpenNewFileEntry(zip_file, relativePath)) {
236         DUMPER_HILOGD(MODULE_COMMON, "AddFileEntryToZip leave|false, open");
237         return false;
238     }
239 
240     bool ret = AddFileContentToZip(zip_file, absolutePath);
241 
242     if (!CloseNewFileEntry(zip_file)) {
243         DUMPER_HILOGD(MODULE_COMMON, "AddFileEntryToZip leave|false, close");
244         return false;
245     }
246 
247     DUMPER_HILOGD(MODULE_COMMON, "AddFileEntryToZip leave|ret=%{public}d", ret);
248     return ret;
249 }
250 } // namespace HiviewDFX
251 } // namespace OHOS
252