xref: /aosp_15_r20/system/libziparchive/zip_archive_stream_entry.cc (revision adcb0a6279ea715828f9bc5e351569419e478774)
1*adcb0a62SAndroid Build Coastguard Worker /*
2*adcb0a62SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*adcb0a62SAndroid Build Coastguard Worker  *
4*adcb0a62SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*adcb0a62SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*adcb0a62SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*adcb0a62SAndroid Build Coastguard Worker  *
8*adcb0a62SAndroid Build Coastguard Worker  *    http://www.apache.org/licenses/LICENSE-2.0
9*adcb0a62SAndroid Build Coastguard Worker  *
10*adcb0a62SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*adcb0a62SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*adcb0a62SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*adcb0a62SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*adcb0a62SAndroid Build Coastguard Worker  * limitations under the License.
15*adcb0a62SAndroid Build Coastguard Worker  */
16*adcb0a62SAndroid Build Coastguard Worker 
17*adcb0a62SAndroid Build Coastguard Worker #define LOG_TAG "ZIPARCHIVE"
18*adcb0a62SAndroid Build Coastguard Worker 
19*adcb0a62SAndroid Build Coastguard Worker // Read-only stream access to Zip Archive entries.
20*adcb0a62SAndroid Build Coastguard Worker #include <errno.h>
21*adcb0a62SAndroid Build Coastguard Worker #include <inttypes.h>
22*adcb0a62SAndroid Build Coastguard Worker #include <string.h>
23*adcb0a62SAndroid Build Coastguard Worker #include <sys/types.h>
24*adcb0a62SAndroid Build Coastguard Worker #include <unistd.h>
25*adcb0a62SAndroid Build Coastguard Worker 
26*adcb0a62SAndroid Build Coastguard Worker #include <limits>
27*adcb0a62SAndroid Build Coastguard Worker #include <memory>
28*adcb0a62SAndroid Build Coastguard Worker #include <vector>
29*adcb0a62SAndroid Build Coastguard Worker 
30*adcb0a62SAndroid Build Coastguard Worker #include <android-base/file.h>
31*adcb0a62SAndroid Build Coastguard Worker #include <android-base/logging.h>
32*adcb0a62SAndroid Build Coastguard Worker #include <log/log.h>
33*adcb0a62SAndroid Build Coastguard Worker 
34*adcb0a62SAndroid Build Coastguard Worker #include <ziparchive/zip_archive.h>
35*adcb0a62SAndroid Build Coastguard Worker #include <ziparchive/zip_archive_stream_entry.h>
36*adcb0a62SAndroid Build Coastguard Worker #include <zlib.h>
37*adcb0a62SAndroid Build Coastguard Worker 
38*adcb0a62SAndroid Build Coastguard Worker #include "zip_archive_private.h"
39*adcb0a62SAndroid Build Coastguard Worker 
40*adcb0a62SAndroid Build Coastguard Worker static constexpr size_t kBufSize = 65535;
41*adcb0a62SAndroid Build Coastguard Worker 
Init(const ZipEntry & entry)42*adcb0a62SAndroid Build Coastguard Worker bool ZipArchiveStreamEntry::Init(const ZipEntry& entry) {
43*adcb0a62SAndroid Build Coastguard Worker   crc32_ = entry.crc32;
44*adcb0a62SAndroid Build Coastguard Worker   offset_ = entry.offset;
45*adcb0a62SAndroid Build Coastguard Worker   return true;
46*adcb0a62SAndroid Build Coastguard Worker }
47*adcb0a62SAndroid Build Coastguard Worker 
48*adcb0a62SAndroid Build Coastguard Worker class ZipArchiveStreamEntryUncompressed : public ZipArchiveStreamEntry {
49*adcb0a62SAndroid Build Coastguard Worker  public:
ZipArchiveStreamEntryUncompressed(ZipArchiveHandle handle)50*adcb0a62SAndroid Build Coastguard Worker   explicit ZipArchiveStreamEntryUncompressed(ZipArchiveHandle handle)
51*adcb0a62SAndroid Build Coastguard Worker       : ZipArchiveStreamEntry(handle) {}
~ZipArchiveStreamEntryUncompressed()52*adcb0a62SAndroid Build Coastguard Worker   virtual ~ZipArchiveStreamEntryUncompressed() {}
53*adcb0a62SAndroid Build Coastguard Worker 
54*adcb0a62SAndroid Build Coastguard Worker   const std::vector<uint8_t>* Read() override;
55*adcb0a62SAndroid Build Coastguard Worker 
56*adcb0a62SAndroid Build Coastguard Worker   bool Verify() override;
57*adcb0a62SAndroid Build Coastguard Worker 
58*adcb0a62SAndroid Build Coastguard Worker  protected:
59*adcb0a62SAndroid Build Coastguard Worker   bool Init(const ZipEntry& entry) override;
60*adcb0a62SAndroid Build Coastguard Worker 
61*adcb0a62SAndroid Build Coastguard Worker   uint32_t length_ = 0u;
62*adcb0a62SAndroid Build Coastguard Worker 
63*adcb0a62SAndroid Build Coastguard Worker  private:
64*adcb0a62SAndroid Build Coastguard Worker   std::vector<uint8_t> data_;
65*adcb0a62SAndroid Build Coastguard Worker   uint32_t computed_crc32_ = 0u;
66*adcb0a62SAndroid Build Coastguard Worker };
67*adcb0a62SAndroid Build Coastguard Worker 
Init(const ZipEntry & entry)68*adcb0a62SAndroid Build Coastguard Worker bool ZipArchiveStreamEntryUncompressed::Init(const ZipEntry& entry) {
69*adcb0a62SAndroid Build Coastguard Worker   if (!ZipArchiveStreamEntry::Init(entry)) {
70*adcb0a62SAndroid Build Coastguard Worker     return false;
71*adcb0a62SAndroid Build Coastguard Worker   }
72*adcb0a62SAndroid Build Coastguard Worker 
73*adcb0a62SAndroid Build Coastguard Worker   length_ = entry.uncompressed_length;
74*adcb0a62SAndroid Build Coastguard Worker 
75*adcb0a62SAndroid Build Coastguard Worker   data_.resize(kBufSize);
76*adcb0a62SAndroid Build Coastguard Worker   computed_crc32_ = 0;
77*adcb0a62SAndroid Build Coastguard Worker 
78*adcb0a62SAndroid Build Coastguard Worker   return true;
79*adcb0a62SAndroid Build Coastguard Worker }
80*adcb0a62SAndroid Build Coastguard Worker 
Read()81*adcb0a62SAndroid Build Coastguard Worker const std::vector<uint8_t>* ZipArchiveStreamEntryUncompressed::Read() {
82*adcb0a62SAndroid Build Coastguard Worker   // Simple validity check. The vector should *only* be handled by this code. A caller
83*adcb0a62SAndroid Build Coastguard Worker   // should not const-cast and modify the capacity. This may invalidate next_out.
84*adcb0a62SAndroid Build Coastguard Worker   //
85*adcb0a62SAndroid Build Coastguard Worker   // Note: it would be better to store the results of data() across Read calls.
86*adcb0a62SAndroid Build Coastguard Worker   CHECK_EQ(data_.capacity(), kBufSize);
87*adcb0a62SAndroid Build Coastguard Worker 
88*adcb0a62SAndroid Build Coastguard Worker   if (length_ == 0) {
89*adcb0a62SAndroid Build Coastguard Worker     return nullptr;
90*adcb0a62SAndroid Build Coastguard Worker   }
91*adcb0a62SAndroid Build Coastguard Worker 
92*adcb0a62SAndroid Build Coastguard Worker   size_t bytes = (length_ > data_.size()) ? data_.size() : length_;
93*adcb0a62SAndroid Build Coastguard Worker   ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle_);
94*adcb0a62SAndroid Build Coastguard Worker   errno = 0;
95*adcb0a62SAndroid Build Coastguard Worker   auto res = archive->mapped_zip.ReadAtOffset(data_.data(), bytes, offset_);
96*adcb0a62SAndroid Build Coastguard Worker   if (!res) {
97*adcb0a62SAndroid Build Coastguard Worker     if (errno != 0) {
98*adcb0a62SAndroid Build Coastguard Worker       ALOGE("Error reading from archive fd: %s", strerror(errno));
99*adcb0a62SAndroid Build Coastguard Worker     } else {
100*adcb0a62SAndroid Build Coastguard Worker       ALOGE("Short read of zip file, possibly corrupted zip?");
101*adcb0a62SAndroid Build Coastguard Worker     }
102*adcb0a62SAndroid Build Coastguard Worker     length_ = 0;
103*adcb0a62SAndroid Build Coastguard Worker     return nullptr;
104*adcb0a62SAndroid Build Coastguard Worker   }
105*adcb0a62SAndroid Build Coastguard Worker 
106*adcb0a62SAndroid Build Coastguard Worker   if (res != data_.data()) {
107*adcb0a62SAndroid Build Coastguard Worker     data_.assign(res, res + bytes);
108*adcb0a62SAndroid Build Coastguard Worker   } else if (bytes < data_.size()) {
109*adcb0a62SAndroid Build Coastguard Worker     data_.resize(bytes);
110*adcb0a62SAndroid Build Coastguard Worker   }
111*adcb0a62SAndroid Build Coastguard Worker   computed_crc32_ = static_cast<uint32_t>(
112*adcb0a62SAndroid Build Coastguard Worker       crc32(computed_crc32_, data_.data(), static_cast<uint32_t>(data_.size())));
113*adcb0a62SAndroid Build Coastguard Worker   length_ -= bytes;
114*adcb0a62SAndroid Build Coastguard Worker   offset_ += bytes;
115*adcb0a62SAndroid Build Coastguard Worker   return &data_;
116*adcb0a62SAndroid Build Coastguard Worker }
117*adcb0a62SAndroid Build Coastguard Worker 
Verify()118*adcb0a62SAndroid Build Coastguard Worker bool ZipArchiveStreamEntryUncompressed::Verify() {
119*adcb0a62SAndroid Build Coastguard Worker   return length_ == 0 && crc32_ == computed_crc32_;
120*adcb0a62SAndroid Build Coastguard Worker }
121*adcb0a62SAndroid Build Coastguard Worker 
122*adcb0a62SAndroid Build Coastguard Worker class ZipArchiveStreamEntryCompressed : public ZipArchiveStreamEntry {
123*adcb0a62SAndroid Build Coastguard Worker  public:
ZipArchiveStreamEntryCompressed(ZipArchiveHandle handle)124*adcb0a62SAndroid Build Coastguard Worker   explicit ZipArchiveStreamEntryCompressed(ZipArchiveHandle handle)
125*adcb0a62SAndroid Build Coastguard Worker       : ZipArchiveStreamEntry(handle) {}
126*adcb0a62SAndroid Build Coastguard Worker   virtual ~ZipArchiveStreamEntryCompressed();
127*adcb0a62SAndroid Build Coastguard Worker 
128*adcb0a62SAndroid Build Coastguard Worker   const std::vector<uint8_t>* Read() override;
129*adcb0a62SAndroid Build Coastguard Worker 
130*adcb0a62SAndroid Build Coastguard Worker   bool Verify() override;
131*adcb0a62SAndroid Build Coastguard Worker 
132*adcb0a62SAndroid Build Coastguard Worker  protected:
133*adcb0a62SAndroid Build Coastguard Worker   bool Init(const ZipEntry& entry) override;
134*adcb0a62SAndroid Build Coastguard Worker 
135*adcb0a62SAndroid Build Coastguard Worker  private:
136*adcb0a62SAndroid Build Coastguard Worker   bool z_stream_init_ = false;
137*adcb0a62SAndroid Build Coastguard Worker   z_stream z_stream_;
138*adcb0a62SAndroid Build Coastguard Worker   std::vector<uint8_t> in_;
139*adcb0a62SAndroid Build Coastguard Worker   std::vector<uint8_t> out_;
140*adcb0a62SAndroid Build Coastguard Worker   uint32_t uncompressed_length_ = 0u;
141*adcb0a62SAndroid Build Coastguard Worker   uint32_t compressed_length_ = 0u;
142*adcb0a62SAndroid Build Coastguard Worker   uint32_t computed_crc32_ = 0u;
143*adcb0a62SAndroid Build Coastguard Worker };
144*adcb0a62SAndroid Build Coastguard Worker 
145*adcb0a62SAndroid Build Coastguard Worker // This method is using libz macros with old-style-casts
146*adcb0a62SAndroid Build Coastguard Worker #pragma GCC diagnostic push
147*adcb0a62SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wold-style-cast"
zlib_inflateInit2(z_stream * stream,int window_bits)148*adcb0a62SAndroid Build Coastguard Worker static inline int zlib_inflateInit2(z_stream* stream, int window_bits) {
149*adcb0a62SAndroid Build Coastguard Worker   return inflateInit2(stream, window_bits);
150*adcb0a62SAndroid Build Coastguard Worker }
151*adcb0a62SAndroid Build Coastguard Worker #pragma GCC diagnostic pop
152*adcb0a62SAndroid Build Coastguard Worker 
Init(const ZipEntry & entry)153*adcb0a62SAndroid Build Coastguard Worker bool ZipArchiveStreamEntryCompressed::Init(const ZipEntry& entry) {
154*adcb0a62SAndroid Build Coastguard Worker   if (!ZipArchiveStreamEntry::Init(entry)) {
155*adcb0a62SAndroid Build Coastguard Worker     return false;
156*adcb0a62SAndroid Build Coastguard Worker   }
157*adcb0a62SAndroid Build Coastguard Worker 
158*adcb0a62SAndroid Build Coastguard Worker   // Initialize the zlib stream struct.
159*adcb0a62SAndroid Build Coastguard Worker   memset(&z_stream_, 0, sizeof(z_stream_));
160*adcb0a62SAndroid Build Coastguard Worker   z_stream_.zalloc = Z_NULL;
161*adcb0a62SAndroid Build Coastguard Worker   z_stream_.zfree = Z_NULL;
162*adcb0a62SAndroid Build Coastguard Worker   z_stream_.opaque = Z_NULL;
163*adcb0a62SAndroid Build Coastguard Worker   z_stream_.next_in = nullptr;
164*adcb0a62SAndroid Build Coastguard Worker   z_stream_.avail_in = 0;
165*adcb0a62SAndroid Build Coastguard Worker   z_stream_.avail_out = 0;
166*adcb0a62SAndroid Build Coastguard Worker   z_stream_.data_type = Z_UNKNOWN;
167*adcb0a62SAndroid Build Coastguard Worker 
168*adcb0a62SAndroid Build Coastguard Worker   // Use the undocumented "negative window bits" feature to tell zlib
169*adcb0a62SAndroid Build Coastguard Worker   // that there's no zlib header waiting for it.
170*adcb0a62SAndroid Build Coastguard Worker   int zerr = zlib_inflateInit2(&z_stream_, -MAX_WBITS);
171*adcb0a62SAndroid Build Coastguard Worker   if (zerr != Z_OK) {
172*adcb0a62SAndroid Build Coastguard Worker     if (zerr == Z_VERSION_ERROR) {
173*adcb0a62SAndroid Build Coastguard Worker       ALOGE("Installed zlib is not compatible with linked version (%s)", ZLIB_VERSION);
174*adcb0a62SAndroid Build Coastguard Worker     } else {
175*adcb0a62SAndroid Build Coastguard Worker       ALOGE("Call to inflateInit2 failed (zerr=%d)", zerr);
176*adcb0a62SAndroid Build Coastguard Worker     }
177*adcb0a62SAndroid Build Coastguard Worker 
178*adcb0a62SAndroid Build Coastguard Worker     return false;
179*adcb0a62SAndroid Build Coastguard Worker   }
180*adcb0a62SAndroid Build Coastguard Worker 
181*adcb0a62SAndroid Build Coastguard Worker   z_stream_init_ = true;
182*adcb0a62SAndroid Build Coastguard Worker 
183*adcb0a62SAndroid Build Coastguard Worker   uncompressed_length_ = entry.uncompressed_length;
184*adcb0a62SAndroid Build Coastguard Worker   compressed_length_ = entry.compressed_length;
185*adcb0a62SAndroid Build Coastguard Worker 
186*adcb0a62SAndroid Build Coastguard Worker   out_.resize(kBufSize);
187*adcb0a62SAndroid Build Coastguard Worker   in_.resize(kBufSize);
188*adcb0a62SAndroid Build Coastguard Worker 
189*adcb0a62SAndroid Build Coastguard Worker   computed_crc32_ = 0;
190*adcb0a62SAndroid Build Coastguard Worker 
191*adcb0a62SAndroid Build Coastguard Worker   return true;
192*adcb0a62SAndroid Build Coastguard Worker }
193*adcb0a62SAndroid Build Coastguard Worker 
~ZipArchiveStreamEntryCompressed()194*adcb0a62SAndroid Build Coastguard Worker ZipArchiveStreamEntryCompressed::~ZipArchiveStreamEntryCompressed() {
195*adcb0a62SAndroid Build Coastguard Worker   if (z_stream_init_) {
196*adcb0a62SAndroid Build Coastguard Worker     inflateEnd(&z_stream_);
197*adcb0a62SAndroid Build Coastguard Worker     z_stream_init_ = false;
198*adcb0a62SAndroid Build Coastguard Worker   }
199*adcb0a62SAndroid Build Coastguard Worker }
200*adcb0a62SAndroid Build Coastguard Worker 
Verify()201*adcb0a62SAndroid Build Coastguard Worker bool ZipArchiveStreamEntryCompressed::Verify() {
202*adcb0a62SAndroid Build Coastguard Worker   return z_stream_init_ && uncompressed_length_ == 0 && compressed_length_ == 0 &&
203*adcb0a62SAndroid Build Coastguard Worker          crc32_ == computed_crc32_;
204*adcb0a62SAndroid Build Coastguard Worker }
205*adcb0a62SAndroid Build Coastguard Worker 
Read()206*adcb0a62SAndroid Build Coastguard Worker const std::vector<uint8_t>* ZipArchiveStreamEntryCompressed::Read() {
207*adcb0a62SAndroid Build Coastguard Worker   // Simple validity check. The vector should *only* be handled by this code. A caller
208*adcb0a62SAndroid Build Coastguard Worker   // should not const-cast and modify the capacity. This may invalidate next_out.
209*adcb0a62SAndroid Build Coastguard Worker   //
210*adcb0a62SAndroid Build Coastguard Worker   // Note: it would be better to store the results of data() across Read calls.
211*adcb0a62SAndroid Build Coastguard Worker   CHECK_EQ(out_.capacity(), kBufSize);
212*adcb0a62SAndroid Build Coastguard Worker 
213*adcb0a62SAndroid Build Coastguard Worker   if (z_stream_.avail_out == 0) {
214*adcb0a62SAndroid Build Coastguard Worker     z_stream_.next_out = out_.data();
215*adcb0a62SAndroid Build Coastguard Worker     z_stream_.avail_out = static_cast<uint32_t>(out_.size());
216*adcb0a62SAndroid Build Coastguard Worker   }
217*adcb0a62SAndroid Build Coastguard Worker 
218*adcb0a62SAndroid Build Coastguard Worker   while (true) {
219*adcb0a62SAndroid Build Coastguard Worker     if (z_stream_.avail_in == 0) {
220*adcb0a62SAndroid Build Coastguard Worker       if (compressed_length_ == 0) {
221*adcb0a62SAndroid Build Coastguard Worker         return nullptr;
222*adcb0a62SAndroid Build Coastguard Worker       }
223*adcb0a62SAndroid Build Coastguard Worker       DCHECK_LE(in_.size(), std::numeric_limits<uint32_t>::max());  // Should be buf size = 64k.
224*adcb0a62SAndroid Build Coastguard Worker       auto bytes = std::min(uint32_t(in_.size()), compressed_length_);
225*adcb0a62SAndroid Build Coastguard Worker       auto archive = reinterpret_cast<ZipArchive*>(handle_);
226*adcb0a62SAndroid Build Coastguard Worker       errno = 0;
227*adcb0a62SAndroid Build Coastguard Worker       auto res = archive->mapped_zip.ReadAtOffset(in_.data(), bytes, offset_);
228*adcb0a62SAndroid Build Coastguard Worker       if (!res) {
229*adcb0a62SAndroid Build Coastguard Worker         if (errno != 0) {
230*adcb0a62SAndroid Build Coastguard Worker           ALOGE("Error reading from archive fd: %s", strerror(errno));
231*adcb0a62SAndroid Build Coastguard Worker         } else {
232*adcb0a62SAndroid Build Coastguard Worker           ALOGE("Short read of zip file, possibly corrupted zip?");
233*adcb0a62SAndroid Build Coastguard Worker         }
234*adcb0a62SAndroid Build Coastguard Worker         return nullptr;
235*adcb0a62SAndroid Build Coastguard Worker       }
236*adcb0a62SAndroid Build Coastguard Worker 
237*adcb0a62SAndroid Build Coastguard Worker       compressed_length_ -= bytes;
238*adcb0a62SAndroid Build Coastguard Worker       offset_ += bytes;
239*adcb0a62SAndroid Build Coastguard Worker       z_stream_.next_in = res;
240*adcb0a62SAndroid Build Coastguard Worker       z_stream_.avail_in = bytes;
241*adcb0a62SAndroid Build Coastguard Worker     }
242*adcb0a62SAndroid Build Coastguard Worker 
243*adcb0a62SAndroid Build Coastguard Worker     int zerr = inflate(&z_stream_, Z_NO_FLUSH);
244*adcb0a62SAndroid Build Coastguard Worker     if (zerr != Z_OK && zerr != Z_STREAM_END) {
245*adcb0a62SAndroid Build Coastguard Worker       ALOGE("inflate zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)", zerr, z_stream_.next_in,
246*adcb0a62SAndroid Build Coastguard Worker             z_stream_.avail_in, z_stream_.next_out, z_stream_.avail_out);
247*adcb0a62SAndroid Build Coastguard Worker       return nullptr;
248*adcb0a62SAndroid Build Coastguard Worker     }
249*adcb0a62SAndroid Build Coastguard Worker 
250*adcb0a62SAndroid Build Coastguard Worker     if (z_stream_.avail_out == 0) {
251*adcb0a62SAndroid Build Coastguard Worker       uncompressed_length_ -= out_.size();
252*adcb0a62SAndroid Build Coastguard Worker       computed_crc32_ = static_cast<uint32_t>(
253*adcb0a62SAndroid Build Coastguard Worker           crc32(computed_crc32_, out_.data(), static_cast<uint32_t>(out_.size())));
254*adcb0a62SAndroid Build Coastguard Worker       return &out_;
255*adcb0a62SAndroid Build Coastguard Worker     }
256*adcb0a62SAndroid Build Coastguard Worker     if (zerr == Z_STREAM_END) {
257*adcb0a62SAndroid Build Coastguard Worker       if (z_stream_.avail_out != 0) {
258*adcb0a62SAndroid Build Coastguard Worker         // Resize the vector down to the actual size of the data.
259*adcb0a62SAndroid Build Coastguard Worker         out_.resize(out_.size() - z_stream_.avail_out);
260*adcb0a62SAndroid Build Coastguard Worker         computed_crc32_ = static_cast<uint32_t>(
261*adcb0a62SAndroid Build Coastguard Worker             crc32(computed_crc32_, out_.data(), static_cast<uint32_t>(out_.size())));
262*adcb0a62SAndroid Build Coastguard Worker         uncompressed_length_ -= out_.size();
263*adcb0a62SAndroid Build Coastguard Worker         return &out_;
264*adcb0a62SAndroid Build Coastguard Worker       }
265*adcb0a62SAndroid Build Coastguard Worker       return nullptr;
266*adcb0a62SAndroid Build Coastguard Worker     }
267*adcb0a62SAndroid Build Coastguard Worker   }
268*adcb0a62SAndroid Build Coastguard Worker   return nullptr;
269*adcb0a62SAndroid Build Coastguard Worker }
270*adcb0a62SAndroid Build Coastguard Worker 
271*adcb0a62SAndroid Build Coastguard Worker class ZipArchiveStreamEntryRawCompressed : public ZipArchiveStreamEntryUncompressed {
272*adcb0a62SAndroid Build Coastguard Worker  public:
ZipArchiveStreamEntryRawCompressed(ZipArchiveHandle handle)273*adcb0a62SAndroid Build Coastguard Worker   explicit ZipArchiveStreamEntryRawCompressed(ZipArchiveHandle handle)
274*adcb0a62SAndroid Build Coastguard Worker       : ZipArchiveStreamEntryUncompressed(handle) {}
~ZipArchiveStreamEntryRawCompressed()275*adcb0a62SAndroid Build Coastguard Worker   virtual ~ZipArchiveStreamEntryRawCompressed() {}
276*adcb0a62SAndroid Build Coastguard Worker 
277*adcb0a62SAndroid Build Coastguard Worker   bool Verify() override;
278*adcb0a62SAndroid Build Coastguard Worker 
279*adcb0a62SAndroid Build Coastguard Worker  protected:
280*adcb0a62SAndroid Build Coastguard Worker   bool Init(const ZipEntry& entry) override;
281*adcb0a62SAndroid Build Coastguard Worker };
282*adcb0a62SAndroid Build Coastguard Worker 
Init(const ZipEntry & entry)283*adcb0a62SAndroid Build Coastguard Worker bool ZipArchiveStreamEntryRawCompressed::Init(const ZipEntry& entry) {
284*adcb0a62SAndroid Build Coastguard Worker   if (!ZipArchiveStreamEntryUncompressed::Init(entry)) {
285*adcb0a62SAndroid Build Coastguard Worker     return false;
286*adcb0a62SAndroid Build Coastguard Worker   }
287*adcb0a62SAndroid Build Coastguard Worker   length_ = entry.compressed_length;
288*adcb0a62SAndroid Build Coastguard Worker 
289*adcb0a62SAndroid Build Coastguard Worker   return true;
290*adcb0a62SAndroid Build Coastguard Worker }
291*adcb0a62SAndroid Build Coastguard Worker 
Verify()292*adcb0a62SAndroid Build Coastguard Worker bool ZipArchiveStreamEntryRawCompressed::Verify() {
293*adcb0a62SAndroid Build Coastguard Worker   return length_ == 0;
294*adcb0a62SAndroid Build Coastguard Worker }
295*adcb0a62SAndroid Build Coastguard Worker 
Create(ZipArchiveHandle handle,const ZipEntry & entry)296*adcb0a62SAndroid Build Coastguard Worker ZipArchiveStreamEntry* ZipArchiveStreamEntry::Create(ZipArchiveHandle handle,
297*adcb0a62SAndroid Build Coastguard Worker                                                      const ZipEntry& entry) {
298*adcb0a62SAndroid Build Coastguard Worker   ZipArchiveStreamEntry* stream = nullptr;
299*adcb0a62SAndroid Build Coastguard Worker   if (entry.method != kCompressStored) {
300*adcb0a62SAndroid Build Coastguard Worker     stream = new ZipArchiveStreamEntryCompressed(handle);
301*adcb0a62SAndroid Build Coastguard Worker   } else {
302*adcb0a62SAndroid Build Coastguard Worker     stream = new ZipArchiveStreamEntryUncompressed(handle);
303*adcb0a62SAndroid Build Coastguard Worker   }
304*adcb0a62SAndroid Build Coastguard Worker   if (stream && !stream->Init(entry)) {
305*adcb0a62SAndroid Build Coastguard Worker     delete stream;
306*adcb0a62SAndroid Build Coastguard Worker     stream = nullptr;
307*adcb0a62SAndroid Build Coastguard Worker   }
308*adcb0a62SAndroid Build Coastguard Worker 
309*adcb0a62SAndroid Build Coastguard Worker   return stream;
310*adcb0a62SAndroid Build Coastguard Worker }
311*adcb0a62SAndroid Build Coastguard Worker 
CreateRaw(ZipArchiveHandle handle,const ZipEntry & entry)312*adcb0a62SAndroid Build Coastguard Worker ZipArchiveStreamEntry* ZipArchiveStreamEntry::CreateRaw(ZipArchiveHandle handle,
313*adcb0a62SAndroid Build Coastguard Worker                                                         const ZipEntry& entry) {
314*adcb0a62SAndroid Build Coastguard Worker   ZipArchiveStreamEntry* stream = nullptr;
315*adcb0a62SAndroid Build Coastguard Worker   if (entry.method == kCompressStored) {
316*adcb0a62SAndroid Build Coastguard Worker     // Not compressed, don't need to do anything special.
317*adcb0a62SAndroid Build Coastguard Worker     stream = new ZipArchiveStreamEntryUncompressed(handle);
318*adcb0a62SAndroid Build Coastguard Worker   } else {
319*adcb0a62SAndroid Build Coastguard Worker     stream = new ZipArchiveStreamEntryRawCompressed(handle);
320*adcb0a62SAndroid Build Coastguard Worker   }
321*adcb0a62SAndroid Build Coastguard Worker   if (stream && !stream->Init(entry)) {
322*adcb0a62SAndroid Build Coastguard Worker     delete stream;
323*adcb0a62SAndroid Build Coastguard Worker     stream = nullptr;
324*adcb0a62SAndroid Build Coastguard Worker   }
325*adcb0a62SAndroid Build Coastguard Worker   return stream;
326*adcb0a62SAndroid Build Coastguard Worker }
327