zipios 2.3.4
Zipios -- a small C++ library providing easy access to .zip files.
zipoutputstreambuf.cpp
Go to the documentation of this file.
1/*
2 Zipios -- a small C++ library that provides easy access to .zip files.
3
4 Copyright (C) 2000-2007 Thomas Sondergaard
5 Copyright (c) 2015-2022 Made to Order Software Corp. All Rights Reserved
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20*/
21
30
32
33#include "ziplocalentry.hpp"
35
36
37namespace zipios
38{
39
40
41namespace
42{
43
44
57 std::ostream & os
58 , FileEntry::vector_t & entries
59 , std::string const & comment)
60{
61 ZipEndOfCentralDirectory eocd(comment);
62 eocd.setOffset(os.tellp()); // start position
63 eocd.setCount(entries.size());
64
65 std::size_t central_directory_size(0);
66 for(auto it = entries.begin(); it != entries.end(); ++it)
67 {
68 (*it)->write(os);
69 central_directory_size += (*it)->getHeaderSize();
70 }
71
72 eocd.setCentralDirectorySize(central_directory_size);
73 eocd.write(os);
74}
75
76
77} // no name namespace
78
79
97{
98}
99
100
115{
116 // avoid possible exceptions when writing the central directory
117 try
118 {
119 finish();
120 }
121 catch(...)
122 {
123 }
124}
125
126
133{
134 if(!m_open_entry)
135 {
136 return;
137 }
138
139 switch(m_compression_level)
140 {
142 overflow(); // flush
143 break;
144
145 default:
146 closeStream();
147 break;
148
149 }
150
153}
154
155
162{
163 finish();
164}
165
166
175{
176 if(!m_open)
177 {
178 return;
179 }
180 m_open = false;
181
182 std::ostream os(m_outbuf);
183 closeEntry();
184 writeZipCentralDirectory(os, m_entries, m_zip_comment);
185}
186
187
199{
200 closeEntry();
201
202 // if the method is STORED force uncompressed data
203 if(entry->getMethod() == StorageMethod::STORED)
204 {
205 // force to "no compression" when the method is STORED
207 }
208 else
209 {
210 // get the user defined compression level
211 m_compression_level = entry->getLevel();
212 }
214 switch(m_compression_level)
215 {
217 setp(&m_invec[0], &m_invec[0] + getBufferSize());
218 break;
219
220 default:
222 break;
223
224 }
225
226 m_entries.push_back(entry);
227
228 std::ostream os(m_outbuf);
229
230 // Update entry header info
231 entry->setEntryOffset(os.tellp());
236 static_cast<ZipLocalEntry *>(entry.get())->ZipLocalEntry::write(os);
237
238 m_open_entry = true;
239}
240
241
254void ZipOutputStreambuf::setComment(std::string const & comment)
255{
256 m_zip_comment = comment;
257}
258
259
260//
261// Protected and private methods
262//
263
279{
280 std::size_t const size(pptr() - pbase());
281 m_overflown_bytes += size;
282 switch(m_compression_level)
283 {
285 {
286 // Ok, we are STORED, so we handle it ourselves to avoid "side
287 // effects" from zlib, which adds markers every now and then.
288 m_crc32 = crc32(m_crc32, reinterpret_cast<Bytef const *>(&m_invec[0]), size); // update crc32
289 size_t const bc(m_outbuf->sputn(&m_invec[0], size));
290 if(size != bc)
291 {
292 // Without implementing our own stream in our test, this
293 // cannot really be reached because it is all happening
294 // inside the same loop in ZipFile::saveCollectionToArchive()
295 throw IOException("ZipOutputStreambuf::overflow(): write to buffer failed."); // LCOV_EXCL_LINE
296 }
297 setp(&m_invec[0], &m_invec[0] + getBufferSize());
298
299 if(c != EOF)
300 {
301 *pptr() = c;
302 pbump(1);
303 }
304
305 return 0;
306 }
307
308 default:
310
311 }
312}
313
314
315
324int ZipOutputStreambuf::sync() // LCOV_EXCL_LINE
325{
326 return DeflateOutputStreambuf::sync(); // LCOV_EXCL_LINE
327}
328
329
330
338{
339 m_open_entry = false;
340 m_crc32 = crc32(0, nullptr, 0);
341
346}
347
348
361{
362 if(!m_open_entry)
363 {
364 return;
365 }
366
367 std::ostream os(m_outbuf);
368 int const curr_pos(os.tellp());
369
370 // update fields in m_entries.back()
371 FileEntry::pointer_t entry(m_entries.back());
372 entry->setSize(getSize());
373 entry->setCrc(getCrc32());
378 entry->setCompressedSize(curr_pos - entry->getEntryOffset() - static_cast<ZipLocalEntry *>(entry.get())->ZipLocalEntry::getHeaderSize());
379
380 // write ZipLocalEntry header to header position
381 os.seekp(entry->getEntryOffset());
386 static_cast<ZipLocalEntry *>(entry.get())->ZipLocalEntry::write(os);
387 os.seekp(curr_pos);
388}
389
390
391} // zipios namespace
392
393// Local Variables:
394// mode: cpp
395// indent-tabs-mode: nil
396// c-basic-offset: 4
397// tab-width: 4
398// End:
399
400// vim: ts=4 sw=4 et
A class to handle stream deflate on the fly.
bool init(FileEntry::CompressionLevel compression_level)
Initialize the zlib library.
uint32_t getCrc32() const
Get the CRC32 of the file.
virtual int sync()
Synchronize the buffer.
virtual int overflow(int c=EOF)
Handle an overflow.
size_t getSize() const
Retrieve the size of the file deflated.
std::shared_ptr< FileEntry > pointer_t
Definition fileentry.hpp:78
static CompressionLevel const COMPRESSION_LEVEL_NONE
Definition fileentry.hpp:90
std::vector< pointer_t > vector_t
Definition fileentry.hpp:79
An IOException is used to signal an I/O error.
Marker at the end of a Zip archive file.
void setOffset(offset_t new_offset)
Offset of the Central Directory.
void write(std::ostream &os)
Write the ZipEndOfCentralDirectory structure to a stream.
void setCentralDirectorySize(size_t size)
Define the size of the central directory.
void setCount(size_t c)
Set the number of entries.
An implementation of the FileEntry for Zip archives.
virtual void write(std::ostream &os) override
Write a ZipLocalEntry to os.
void setComment(std::string const &comment)
Set the archive comment.
ZipOutputStreambuf(std::streambuf *outbuf)
Initialize a ZipOutputStreambuf object.
virtual ~ZipOutputStreambuf()
Clean up the buffer.
void close()
Close the output stream buffer.
void putNextEntry(FileEntry::pointer_t entry)
Start saving an entry in the output buffer.
void closeEntry()
Close this buffer entry.
FileEntry::CompressionLevel m_compression_level
virtual int sync() override
Implement the sync() functionality.
void updateEntryHeaderInfo()
Save the header information.
virtual int overflow(int c=EOF) override
Implementation of the overflow() function.
void finish()
Finish up an output stream buffer.
void setEntryClosedState()
Mark the current entry as closed.
void writeZipCentralDirectory(std::ostream &os, FileEntry::vector_t &entries, std::string const &comment)
Helper function used to write the central directory.
The zipios namespace includes the Zipios library definitions.
size_t getBufferSize()
Declaration of the zipios::ZipEndOfCentralDirectory class.
Various exceptions used throughout the Zipios library, all based on zipios::Exception.
Declare the zipios::ZipLocalEntry class used to handle Zip entries.
Define the zipios::ZipOutputStreambuf class.