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 
16 #include "zip_adapter.h"
17 #include <iostream>
18 #include <vector>
19 #include "zlib.h"
20 
21 using namespace Hpackage;
22 
23 namespace UpdatePatch {
ZipAdapter(UpdatePatchWriterPtr outStream,size_t offset,const PkgManager::FileInfoPtr fileInfo)24 ZipAdapter::ZipAdapter(UpdatePatchWriterPtr outStream, size_t offset, const PkgManager::FileInfoPtr fileInfo)
25     : DeflateAdapter(), outStream_(outStream), offset_(offset)
26 {
27     const Hpackage::ZipFileInfo *info = (const Hpackage::ZipFileInfo *)fileInfo;
28     method_ = info->method;
29     level_ = info->level;
30     windowBits_ = info->windowBits;
31     memLevel_ = info->memLevel;
32     strategy_ = info->strategy;
33 }
34 
Open()35 int32_t ZipAdapter::Open()
36 {
37     if (init_) {
38         PATCH_LOGE("Has been open");
39         return 0;
40     }
41     if (memset_s(&zstream_, sizeof(zstream_), 0, sizeof(z_stream)) != EOK) {
42         PATCH_LOGE("Failed to memset stream");
43         return -1;
44     }
45     PATCH_DEBUG("Open level_:%d method_:%d windowBits_:%d memLevel_:%d strategy_:%d",
46         level_, method_, windowBits_, memLevel_, strategy_);
47     int32_t ret = deflateInit2(&zstream_, level_, method_, windowBits_, memLevel_, strategy_);
48     if (ret != Z_OK) {
49         PATCH_LOGE("Failed to deflateInit2 ret %d", ret);
50         return -1;
51     }
52     buffer_.resize(BUFFER_SIZE);
53     init_ = true;
54     return ret;
55 }
56 
Close()57 int32_t ZipAdapter::Close()
58 {
59     if (!init_) {
60         PATCH_LOGE("Has been close");
61         return 0;
62     }
63     int32_t ret = deflateEnd(&zstream_);
64     if (ret != Z_OK) {
65         PATCH_LOGE("Failed to deflateEnd %d", ret);
66         return -1;
67     }
68     init_ = false;
69     return ret;
70 }
71 
WriteData(const BlockBuffer & srcData)72 int32_t ZipAdapter::WriteData(const BlockBuffer &srcData)
73 {
74     zstream_.next_in = srcData.buffer;
75     zstream_.avail_in = static_cast<uint32_t>(srcData.length);
76     zstream_.avail_out =  static_cast<uint32_t>(buffer_.size());
77     zstream_.next_out = reinterpret_cast<unsigned char*>(buffer_.data());
78     size_t deflateLen = 0;
79     int32_t ret = Z_OK;
80     do {
81         ret = deflate(&zstream_, Z_NO_FLUSH);
82         deflateLen = buffer_.size() -  zstream_.avail_out;
83         if (deflateLen > 0) {
84             ret = outStream_->Write(offset_, {buffer_.data(), deflateLen}, deflateLen);
85             if (ret != 0) {
86                 PATCH_LOGE("Failed to deflate data");
87                 return -1;
88             }
89             offset_ += deflateLen;
90 
91             zstream_.next_out = reinterpret_cast<unsigned char*>(buffer_.data());
92             zstream_.avail_out = buffer_.size();
93         }
94         if (zstream_.avail_in == 0) {
95             break;
96         }
97     } while (ret == Z_OK);
98     if (ret != Z_OK) {
99         PATCH_LOGE("WriteData : Failed to write data ret %d", ret);
100         return ret;
101     }
102     if (zstream_.avail_in != 0) {
103         PATCH_LOGE("WriteData : Failed to write data");
104         return ret;
105     }
106     return ret;
107 }
108 
FlushData(size_t & offset)109 int32_t ZipAdapter::FlushData(size_t &offset)
110 {
111     zstream_.next_in = nullptr;
112     zstream_.avail_in = 0;
113     zstream_.avail_out =  buffer_.size();
114     zstream_.next_out = reinterpret_cast<unsigned char*>(buffer_.data());
115     size_t deflateLen = 0;
116     int32_t ret = Z_OK;
117     do {
118         ret = deflate(&zstream_, Z_FINISH);
119         deflateLen = buffer_.size() -  zstream_.avail_out;
120         if (deflateLen > 0) {
121             ret = outStream_->Write(offset_, {buffer_.data(), deflateLen}, deflateLen);
122             if (ret != 0) {
123                 PATCH_LOGE("Failed to deflate data");
124                 return 1;
125             }
126             offset_ += deflateLen;
127 
128             zstream_.next_out = reinterpret_cast<unsigned char*>(buffer_.data());
129             zstream_.avail_out = buffer_.size();
130         }
131         if (ret == Z_STREAM_END) {
132             ret = Z_OK;
133             break;
134         }
135     } while (ret == Z_OK);
136     if (ret != Z_OK) {
137         PATCH_LOGE("FlushData : Failed to write data ret %d", ret);
138         return ret;
139     }
140     if (zstream_.avail_in != 0) {
141         PATCH_LOGE("FlushData : Failed to write data");
142         return ret;
143     }
144     offset = offset_;
145     return ret;
146 }
147 } // namespace UpdatePatch
148