|
25 | 25 | #include "util/ZipSerialize.h" |
26 | 26 |
|
27 | 27 | #include <array> |
| 28 | +#include <filesystem> |
28 | 29 | #include <fstream> |
29 | 30 | #include <sstream> |
30 | 31 |
|
@@ -106,25 +107,48 @@ DataFilePrivate::DataFilePrivate(const ZipSerialize &z, string filename, string |
106 | 107 | d->size.emplace((unsigned long)r.size); |
107 | 108 | if(r.size > MAX_MEM_FILE) |
108 | 109 | { |
109 | | - auto fs = make_unique<fstream>(util::File::tempFileName(), fstream::in|fstream::out|fstream::binary|fstream::trunc); |
110 | | - if(!fs->is_open()) |
111 | | - THROW("Failed to open destination file"); |
112 | | - array<char,10240> buf{}; |
113 | | - for(size_t size = 0, currentStreamSize = 0; |
114 | | - (size = r(buf.data(), buf.size())) > 0; currentStreamSize += size) |
115 | | - { |
116 | | - if(currentStreamSize + size > r.size) |
117 | | - THROW("ZIP entry actual size exceeds uncompressed_size %zu", r.size); |
118 | | - if(!fs->write(buf.data(), size)) |
119 | | - THROW("Failed to write '%s' data to stream. Stream size: %d", m_filename.c_str(), currentStreamSize); |
| 110 | + try { |
| 111 | + m_tempFile = util::File::tempFileName(); |
| 112 | + auto fs = make_unique<fstream>(m_tempFile, fstream::in|fstream::out|fstream::binary|fstream::trunc); |
| 113 | + if(!fs->is_open()) |
| 114 | + THROW("Failed to open destination file"); |
| 115 | + array<char,10240> buf{}; |
| 116 | + for(size_t size = 0, currentStreamSize = 0; |
| 117 | + (size = r(buf.data(), buf.size())) > 0; currentStreamSize += size) |
| 118 | + { |
| 119 | + if(currentStreamSize + size > r.size) |
| 120 | + THROW("ZIP entry actual size exceeds uncompressed_size %zu", r.size); |
| 121 | + if(!fs->write(buf.data(), size)) |
| 122 | + THROW("Failed to write '%s' data to stream. Stream size: %d", m_filename.c_str(), currentStreamSize); |
| 123 | + } |
| 124 | + if(!fs->flush()) |
| 125 | + THROW("Failed to flush '%s' data to temporary file.", m_filename.c_str()); |
| 126 | + fs->clear(); |
| 127 | + if(!fs->seekg(0, istream::beg)) |
| 128 | + THROW("Failed to rewind '%s' temporary file.", m_filename.c_str()); |
| 129 | + m_is = std::move(fs); |
| 130 | + } catch(...) { |
| 131 | + if(!m_tempFile.empty()) |
| 132 | + { |
| 133 | + error_code ec; |
| 134 | + filesystem::remove(m_tempFile, ec); |
| 135 | + } |
| 136 | + throw; |
120 | 137 | } |
121 | | - m_is = std::move(fs); |
122 | 138 | } |
123 | 139 | else |
124 | 140 | m_is = make_unique<stringstream>(r(MAX_MEM_FILE)); |
125 | 141 | } |
126 | 142 |
|
127 | | -DataFilePrivate::~DataFilePrivate() noexcept = default; |
| 143 | +DataFilePrivate::~DataFilePrivate() noexcept |
| 144 | +{ |
| 145 | + m_is.reset(); |
| 146 | + if(!m_tempFile.empty()) |
| 147 | + { |
| 148 | + error_code ec; |
| 149 | + filesystem::remove(m_tempFile, ec); |
| 150 | + } |
| 151 | +} |
128 | 152 |
|
129 | 153 | void DataFilePrivate::digest(const Digest &digest) const |
130 | 154 | { |
|
0 commit comments