Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Side by Side Diff: ui/file_manager/zip_archiver/cpp/compressor_archive_libarchive.cc

Issue 2818673004: Rename filenames that end with libarchive with minizip. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "compressor_archive_libarchive.h"
6
7 #include <cerrno>
8 #include <cstring>
9
10 #include "base/time/time.h"
11 #include "ppapi/cpp/logging.h"
12
13 namespace compressor_archive_functions {
14
15 // Called when minizip tries to open a zip archive file. We do nothing here
16 // because JavaScript takes care of file opening operation.
17 void* CustomArchiveOpen(void* compressor,
18 const char* /*filename*/, int /*mode*/) {
19 return compressor;
20 }
21
22 // This function is not called because we don't unpack zip files here.
23 uLong CustomArchiveRead(void* /*compressor*/, void* /*stream*/,
24 void* /*buffur*/, uLong /*size*/) {
25 return 0 /* Success */;
26 }
27
28 // Called when data chunk must be written on the archive. It copies data
29 // from the given buffer processed by minizip to an array buffer and passes
30 // it to compressor_stream.
31 uLong CustomArchiveWrite(void* compressor,
32 void* /*stream*/,
33 const void* zip_buffer,
34 uLong zip_length) {
35 CompressorArchiveMinizip* compressor_minizip =
36 static_cast<CompressorArchiveMinizip*>(compressor);
37
38 int64_t written_bytes = compressor_minizip->compressor_stream()->Write(
39 compressor_minizip->offset_, zip_length,
40 static_cast<const char*>(zip_buffer));
41
42 if (written_bytes != zip_length)
43 return 0 /* Error */;
44
45 // Update offset_ and length_.
46 compressor_minizip->offset_ += written_bytes;
47 if (compressor_minizip->offset_ > compressor_minizip->length_)
48 compressor_minizip->length_ = compressor_minizip->offset_;
49 return static_cast<uLong>(written_bytes);
50 }
51
52 // Returns the offset from the beginning of the data.
53 long CustomArchiveTell(void* compressor, void* /*stream*/) {
54 CompressorArchiveMinizip* compressor_minizip =
55 static_cast<CompressorArchiveMinizip*>(compressor);
56 return static_cast<long>(compressor_minizip->offset_);
57 }
58
59 // Moves the current offset to the specified position.
60 long CustomArchiveSeek(void* compressor,
61 void* /*stream*/,
62 uLong offset,
63 int origin) {
64 CompressorArchiveMinizip* compressor_minizip =
65 static_cast<CompressorArchiveMinizip*>(compressor);
66
67 if (origin == ZLIB_FILEFUNC_SEEK_CUR) {
68 compressor_minizip->offset_ =
69 std::min(compressor_minizip->offset_ + static_cast<int64_t>(offset),
70 compressor_minizip->length_);
71 return 0 /* Success */;
72 }
73 if (origin == ZLIB_FILEFUNC_SEEK_END) {
74 compressor_minizip->offset_ =
75 std::max(compressor_minizip->length_ - static_cast<int64_t>(offset),
76 0LL);
77 return 0 /* Success */;
78 }
79 if (origin == ZLIB_FILEFUNC_SEEK_SET) {
80 compressor_minizip->offset_ =
81 std::min(static_cast<int64_t>(offset), compressor_minizip->length_);
82 return 0 /* Success */;
83 }
84 return -1 /* Error */;
85 }
86
87 // Releases all used resources. compressor points to compressor_minizip and
88 // it is deleted in the destructor of Compressor, so we don't need to delete
89 // it here.
90 int CustomArchiveClose(void* /*compressor*/, void* /*stream*/) {
91 return 0 /* Success */;
92 }
93
94 // Returns the last error that happened when writing data. This function always
95 // returns zero, which means there are no errors.
96 int CustomArchiveError(void* /*compressor*/, void* /*stream*/) {
97 return 0 /* Success */;
98 }
99
100 } // compressor_archive_functions
101
102 CompressorArchiveMinizip::CompressorArchiveMinizip(
103 CompressorStream* compressor_stream)
104 : CompressorArchive(compressor_stream),
105 compressor_stream_(compressor_stream),
106 zip_file_(nullptr),
107 offset_(0),
108 length_(0) {
109 destination_buffer_ =
110 new char[compressor_stream_constants::kMaximumDataChunkSize];
111 }
112
113 CompressorArchiveMinizip::~CompressorArchiveMinizip() {
114 delete destination_buffer_;
115 }
116
117 bool CompressorArchiveMinizip::CreateArchive() {
118 // Set up archive object.
119 zlib_filefunc_def zip_funcs;
120 zip_funcs.zopen_file = compressor_archive_functions::CustomArchiveOpen;
121 zip_funcs.zread_file = compressor_archive_functions::CustomArchiveRead;
122 zip_funcs.zwrite_file = compressor_archive_functions::CustomArchiveWrite;
123 zip_funcs.ztell_file = compressor_archive_functions::CustomArchiveTell;
124 zip_funcs.zseek_file = compressor_archive_functions::CustomArchiveSeek;
125 zip_funcs.zclose_file = compressor_archive_functions::CustomArchiveClose;
126 zip_funcs.zerror_file = compressor_archive_functions::CustomArchiveError;
127 zip_funcs.opaque = this;
128
129 zip_file_ = zipOpen2(nullptr /* pathname */,
130 APPEND_STATUS_CREATE,
131 nullptr /* globalcomment */,
132 &zip_funcs);
133 if (!zip_file_) {
134 set_error_message(compressor_archive_constants::kCreateArchiveError);
135 return false /* Error */;
136 }
137 return true /* Success */;
138 }
139
140 bool CompressorArchiveMinizip::AddToArchive(const std::string& filename,
141 int64_t file_size,
142 int64_t modification_time,
143 bool is_directory) {
144 // Minizip takes filenames that end with '/' as directories.
145 std::string normalized_filename = filename;
146 if (is_directory)
147 normalized_filename += "/";
148
149 // Fill zipfileMetadata with modification_time.
150 zip_fileinfo zipfileMetadata;
151 // modification_time is millisecond-based, while FromTimeT takes seconds.
152 base::Time tm = base::Time::FromTimeT((int64_t)modification_time / 1000);
153 base::Time::Exploded exploded_time = {};
154 tm.LocalExplode(&exploded_time);
155 zipfileMetadata.tmz_date.tm_sec = exploded_time.second;
156 zipfileMetadata.tmz_date.tm_min = exploded_time.minute;
157 zipfileMetadata.tmz_date.tm_hour = exploded_time.hour;
158 zipfileMetadata.tmz_date.tm_year = exploded_time.year;
159 zipfileMetadata.tmz_date.tm_mday = exploded_time.day_of_month;
160 // Convert from 1-based to 0-based.
161 zipfileMetadata.tmz_date.tm_mon = exploded_time.month - 1;
162
163 // Section 4.4.4 http://www.pkware.com/documents/casestudies/APPNOTE.TXT
164 // Setting the Language encoding flag so the file is told to be in utf-8.
165 const uLong LANGUAGE_ENCODING_FLAG = 0x1 << 11;
166
167 int open_result = zipOpenNewFileInZip4(zip_file_, // file
168 normalized_filename.c_str(),// filename
169 &zipfileMetadata, // zipfi
170 nullptr, // extrafield_local
171 0u, // size_extrafield_local
172 nullptr, // extrafield_global
173 0u, // size_extrafield_global
174 nullptr, // comment
175 Z_DEFLATED, // method
176 Z_DEFAULT_COMPRESSION, // level
177 0, // raw
178 -MAX_WBITS, // windowBits
179 DEF_MEM_LEVEL, // memLevel
180 Z_DEFAULT_STRATEGY, // strategy
181 nullptr, // password
182 0, // crcForCrypting
183 0, // versionMadeBy
184 LANGUAGE_ENCODING_FLAG); // flagBase
185 if (open_result != ZIP_OK) {
186 CloseArchive(true /* has_error */);
187 set_error_message(compressor_archive_constants::kAddToArchiveError);
188 return false /* Error */;
189 }
190
191 bool has_error = false;
192 if (!is_directory) {
193 int64_t remaining_size = file_size;
194 while (remaining_size > 0) {
195 int64_t chunk_size = std::min(remaining_size,
196 compressor_stream_constants::kMaximumDataChunkSize);
197 PP_DCHECK(chunk_size > 0);
198
199 int64_t read_bytes =
200 compressor_stream_->Read(chunk_size, destination_buffer_);
201
202 // Negative read_bytes indicates an error occurred when reading chunks.
203 // 0 just means there is no more data available, but here we need positive
204 // length of bytes, so this is also an error here.
205 if (read_bytes <= 0) {
206 has_error = true;
207 break;
208 }
209
210 if (zipWriteInFileInZip(zip_file_, destination_buffer_, read_bytes) !=
211 ZIP_OK) {
212 has_error = true;
213 break;
214 }
215 remaining_size -= read_bytes;
216 }
217 }
218
219 if (!has_error && zipCloseFileInZip(zip_file_) != ZIP_OK)
220 has_error = true;
221
222 if (has_error) {
223 CloseArchive(true /* has_error */);
224 set_error_message(compressor_archive_constants::kAddToArchiveError);
225 return false /* Error */;
226 }
227
228 return true /* Success */;
229 }
230
231 bool CompressorArchiveMinizip::CloseArchive(bool has_error) {
232 if (zipClose(zip_file_, nullptr /* global_comment */) != ZIP_OK) {
233 set_error_message(compressor_archive_constants::kCloseArchiveError);
234 return false /* Error */;
235 }
236 if (!has_error) {
237 if (compressor_stream()->Flush() < 0) {
238 set_error_message(compressor_archive_constants::kCloseArchiveError);
239 return false /* Error */;
240 }
241 }
242 return true /* Success */;
243 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698