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

Side by Side Diff: third_party/zlib/google/zip_reader.cc

Issue 1016813004: Revert of Add ZipReader::ExtractCurrentEntry with a delegate interface. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 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
« no previous file with comments | « third_party/zlib/google/zip_reader.h ('k') | third_party/zlib/google/zip_reader_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "third_party/zlib/google/zip_reader.h" 5 #include "third_party/zlib/google/zip_reader.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/files/file.h" 8 #include "base/files/file.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "third_party/zlib/google/zip_internal.h" 13 #include "third_party/zlib/google/zip_internal.h"
14 14
15 #if defined(USE_SYSTEM_MINIZIP) 15 #if defined(USE_SYSTEM_MINIZIP)
16 #include <minizip/unzip.h> 16 #include <minizip/unzip.h>
17 #else 17 #else
18 #include "third_party/zlib/contrib/minizip/unzip.h" 18 #include "third_party/zlib/contrib/minizip/unzip.h"
19 #if defined(OS_WIN) 19 #if defined(OS_WIN)
20 #include "third_party/zlib/contrib/minizip/iowin32.h" 20 #include "third_party/zlib/contrib/minizip/iowin32.h"
21 #endif // defined(OS_WIN) 21 #endif // defined(OS_WIN)
22 #endif // defined(USE_SYSTEM_MINIZIP) 22 #endif // defined(USE_SYSTEM_MINIZIP)
23 23
24 namespace zip { 24 namespace zip {
25 25
26 namespace {
27
28 // FilePathWriterDelegate ------------------------------------------------------
29
30 // A writer delegate that writes a file at a given path.
31 class FilePathWriterDelegate : public WriterDelegate {
32 public:
33 explicit FilePathWriterDelegate(const base::FilePath& output_file_path);
34 ~FilePathWriterDelegate() override;
35
36 // WriterDelegate methods:
37
38 // Creates the output file and any necessary intermediate directories.
39 bool PrepareOutput() override;
40
41 // Writes |num_bytes| bytes of |data| to the file, returning false if not all
42 // bytes could be written.
43 bool WriteBytes(const char* data, int num_bytes) override;
44
45 private:
46 base::FilePath output_file_path_;
47 base::File file_;
48
49 DISALLOW_COPY_AND_ASSIGN(FilePathWriterDelegate);
50 };
51
52 FilePathWriterDelegate::FilePathWriterDelegate(
53 const base::FilePath& output_file_path)
54 : output_file_path_(output_file_path) {
55 }
56
57 FilePathWriterDelegate::~FilePathWriterDelegate() {
58 }
59
60 bool FilePathWriterDelegate::PrepareOutput() {
61 // We can't rely on parent directory entries being specified in the
62 // zip, so we make sure they are created.
63 if (!base::CreateDirectory(output_file_path_.DirName()))
64 return false;
65
66 file_.Initialize(output_file_path_,
67 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
68 return file_.IsValid();
69 }
70
71 bool FilePathWriterDelegate::WriteBytes(const char* data, int num_bytes) {
72 return num_bytes == file_.WriteAtCurrentPos(data, num_bytes);
73 }
74
75
76 // StringWriterDelegate --------------------------------------------------------
77
78 // A writer delegate that writes no more than |max_read_bytes| to a given
79 // std::string.
80 class StringWriterDelegate : public WriterDelegate {
81 public:
82 StringWriterDelegate(size_t max_read_bytes, std::string* output);
83 ~StringWriterDelegate() override;
84
85 // WriterDelegate methods:
86
87 // Returns true.
88 bool PrepareOutput() override;
89
90 // Appends |num_bytes| bytes from |data| to the output string. Returns false
91 // if |num_bytes| will cause the string to exceed |max_read_bytes|.
92 bool WriteBytes(const char* data, int num_bytes) override;
93
94 private:
95 size_t max_read_bytes_;
96 std::string* output_;
97
98 DISALLOW_COPY_AND_ASSIGN(StringWriterDelegate);
99 };
100
101 StringWriterDelegate::StringWriterDelegate(size_t max_read_bytes,
102 std::string* output)
103 : max_read_bytes_(max_read_bytes),
104 output_(output) {
105 }
106
107 StringWriterDelegate::~StringWriterDelegate() {
108 }
109
110 bool StringWriterDelegate::PrepareOutput() {
111 return true;
112 }
113
114 bool StringWriterDelegate::WriteBytes(const char* data, int num_bytes) {
115 if (output_->size() + num_bytes > max_read_bytes_)
116 return false;
117 output_->append(data, num_bytes);
118 return true;
119 }
120
121 } // namespace
122
123 // TODO(satorux): The implementation assumes that file names in zip files 26 // TODO(satorux): The implementation assumes that file names in zip files
124 // are encoded in UTF-8. This is true for zip files created by Zip() 27 // are encoded in UTF-8. This is true for zip files created by Zip()
125 // function in zip.h, but not true for user-supplied random zip files. 28 // function in zip.h, but not true for user-supplied random zip files.
126 ZipReader::EntryInfo::EntryInfo(const std::string& file_name_in_zip, 29 ZipReader::EntryInfo::EntryInfo(const std::string& file_name_in_zip,
127 const unz_file_info& raw_file_info) 30 const unz_file_info& raw_file_info)
128 : file_path_(base::FilePath::FromUTF8Unsafe(file_name_in_zip)), 31 : file_path_(base::FilePath::FromUTF8Unsafe(file_name_in_zip)),
129 is_directory_(false) { 32 is_directory_(false) {
130 original_size_ = raw_file_info.uncompressed_size; 33 original_size_ = raw_file_info.uncompressed_size;
131 34
132 // Directory entries in zip files end with "/". 35 // Directory entries in zip files end with "/".
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 const int result = unzLocateFile(zip_file_, 180 const int result = unzLocateFile(zip_file_,
278 path_in_zip.AsUTF8Unsafe().c_str(), 181 path_in_zip.AsUTF8Unsafe().c_str(),
279 kDefaultCaseSensivityOfOS); 182 kDefaultCaseSensivityOfOS);
280 if (result != UNZ_OK) 183 if (result != UNZ_OK)
281 return false; 184 return false;
282 185
283 // Then Open the entry. 186 // Then Open the entry.
284 return OpenCurrentEntryInZip(); 187 return OpenCurrentEntryInZip();
285 } 188 }
286 189
287 bool ZipReader::ExtractCurrentEntry(WriterDelegate* delegate) const { 190 bool ZipReader::ExtractCurrentEntryToFilePath(
191 const base::FilePath& output_file_path) {
288 DCHECK(zip_file_); 192 DCHECK(zip_file_);
289 193
194 // If this is a directory, just create it and return.
195 if (current_entry_info()->is_directory())
196 return base::CreateDirectory(output_file_path);
197
290 const int open_result = unzOpenCurrentFile(zip_file_); 198 const int open_result = unzOpenCurrentFile(zip_file_);
291 if (open_result != UNZ_OK) 199 if (open_result != UNZ_OK)
292 return false; 200 return false;
293 201
294 if (!delegate->PrepareOutput()) 202 // We can't rely on parent directory entries being specified in the
203 // zip, so we make sure they are created.
204 base::FilePath output_dir_path = output_file_path.DirName();
205 if (!base::CreateDirectory(output_dir_path))
206 return false;
207
208 base::File file(output_file_path,
209 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
210 if (!file.IsValid())
295 return false; 211 return false;
296 212
297 bool success = true; // This becomes false when something bad happens. 213 bool success = true; // This becomes false when something bad happens.
298 scoped_ptr<char[]> buf(new char[internal::kZipBufSize]);
299 while (true) { 214 while (true) {
300 const int num_bytes_read = unzReadCurrentFile(zip_file_, buf.get(), 215 char buf[internal::kZipBufSize];
216 const int num_bytes_read = unzReadCurrentFile(zip_file_, buf,
301 internal::kZipBufSize); 217 internal::kZipBufSize);
302 if (num_bytes_read == 0) { 218 if (num_bytes_read == 0) {
303 // Reached the end of the file. 219 // Reached the end of the file.
304 break; 220 break;
305 } else if (num_bytes_read < 0) { 221 } else if (num_bytes_read < 0) {
306 // If num_bytes_read < 0, then it's a specific UNZ_* error code. 222 // If num_bytes_read < 0, then it's a specific UNZ_* error code.
307 success = false; 223 success = false;
308 break; 224 break;
309 } else if (num_bytes_read > 0) { 225 } else if (num_bytes_read > 0) {
310 // Some data is read. 226 // Some data is read. Write it to the output file.
311 if (!delegate->WriteBytes(buf.get(), num_bytes_read)) { 227 if (num_bytes_read != file.WriteAtCurrentPos(buf, num_bytes_read)) {
312 success = false; 228 success = false;
313 break; 229 break;
314 } 230 }
315 } 231 }
316 } 232 }
317 233
234 file.Close();
318 unzCloseCurrentFile(zip_file_); 235 unzCloseCurrentFile(zip_file_);
319 236
237 if (current_entry_info()->last_modified() != base::Time::UnixEpoch())
238 base::TouchFile(output_file_path,
239 base::Time::Now(),
240 current_entry_info()->last_modified());
241
320 return success; 242 return success;
321 } 243 }
322
323 bool ZipReader::ExtractCurrentEntryToFilePath(
324 const base::FilePath& output_file_path) const {
325 DCHECK(zip_file_);
326
327 // If this is a directory, just create it and return.
328 if (current_entry_info()->is_directory())
329 return base::CreateDirectory(output_file_path);
330
331 bool success = false;
332 {
333 FilePathWriterDelegate writer(output_file_path);
334 success = ExtractCurrentEntry(&writer);
335 }
336
337 if (success &&
338 current_entry_info()->last_modified() != base::Time::UnixEpoch()) {
339 base::TouchFile(output_file_path,
340 base::Time::Now(),
341 current_entry_info()->last_modified());
342 }
343
344 return success;
345 }
346 244
347 void ZipReader::ExtractCurrentEntryToFilePathAsync( 245 void ZipReader::ExtractCurrentEntryToFilePathAsync(
348 const base::FilePath& output_file_path, 246 const base::FilePath& output_file_path,
349 const SuccessCallback& success_callback, 247 const SuccessCallback& success_callback,
350 const FailureCallback& failure_callback, 248 const FailureCallback& failure_callback,
351 const ProgressCallback& progress_callback) { 249 const ProgressCallback& progress_callback) {
352 DCHECK(zip_file_); 250 DCHECK(zip_file_);
353 DCHECK(current_entry_info_.get()); 251 DCHECK(current_entry_info_.get());
354 252
355 // If this is a directory, just create it and return. 253 // If this is a directory, just create it and return.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 base::Bind(&ZipReader::ExtractChunk, 289 base::Bind(&ZipReader::ExtractChunk,
392 weak_ptr_factory_.GetWeakPtr(), 290 weak_ptr_factory_.GetWeakPtr(),
393 Passed(output_file.Pass()), 291 Passed(output_file.Pass()),
394 success_callback, 292 success_callback,
395 failure_callback, 293 failure_callback,
396 progress_callback, 294 progress_callback,
397 0 /* initial offset */)); 295 0 /* initial offset */));
398 } 296 }
399 297
400 bool ZipReader::ExtractCurrentEntryIntoDirectory( 298 bool ZipReader::ExtractCurrentEntryIntoDirectory(
401 const base::FilePath& output_directory_path) const { 299 const base::FilePath& output_directory_path) {
402 DCHECK(current_entry_info_.get()); 300 DCHECK(current_entry_info_.get());
403 301
404 base::FilePath output_file_path = output_directory_path.Append( 302 base::FilePath output_file_path = output_directory_path.Append(
405 current_entry_info()->file_path()); 303 current_entry_info()->file_path());
406 return ExtractCurrentEntryToFilePath(output_file_path); 304 return ExtractCurrentEntryToFilePath(output_file_path);
407 } 305 }
408 306
409 bool ZipReader::ExtractCurrentEntryToFile(base::File* file) const { 307 #if defined(OS_POSIX)
308 bool ZipReader::ExtractCurrentEntryToFd(const int fd) {
410 DCHECK(zip_file_); 309 DCHECK(zip_file_);
411 310
412 // If this is a directory, there's nothing to extract to the file, so return 311 // If this is a directory, there's nothing to extract to the file descriptor,
413 // false. 312 // so return false.
414 if (current_entry_info()->is_directory()) 313 if (current_entry_info()->is_directory())
415 return false; 314 return false;
416 315
417 FileWriterDelegate writer(file); 316 const int open_result = unzOpenCurrentFile(zip_file_);
418 return ExtractCurrentEntry(&writer); 317 if (open_result != UNZ_OK)
318 return false;
319
320 bool success = true; // This becomes false when something bad happens.
321 while (true) {
322 char buf[internal::kZipBufSize];
323 const int num_bytes_read = unzReadCurrentFile(zip_file_, buf,
324 internal::kZipBufSize);
325 if (num_bytes_read == 0) {
326 // Reached the end of the file.
327 break;
328 } else if (num_bytes_read < 0) {
329 // If num_bytes_read < 0, then it's a specific UNZ_* error code.
330 success = false;
331 break;
332 } else if (num_bytes_read > 0) {
333 // Some data is read. Write it to the output file descriptor.
334 if (!base::WriteFileDescriptor(fd, buf, num_bytes_read)) {
335 success = false;
336 break;
337 }
338 }
339 }
340
341 unzCloseCurrentFile(zip_file_);
342 return success;
419 } 343 }
344 #endif // defined(OS_POSIX)
420 345
421 bool ZipReader::ExtractCurrentEntryToString(size_t max_read_bytes, 346 bool ZipReader::ExtractCurrentEntryToString(
422 std::string* output) const { 347 size_t max_read_bytes,
348 std::string* output) const {
423 DCHECK(output); 349 DCHECK(output);
424 DCHECK(zip_file_); 350 DCHECK(zip_file_);
425 DCHECK_NE(0U, max_read_bytes); 351 DCHECK(max_read_bytes != 0);
426 352
427 if (current_entry_info()->is_directory()) { 353 if (current_entry_info()->is_directory()) {
428 output->clear(); 354 output->clear();
429 return true; 355 return true;
430 } 356 }
431 357
358 const int open_result = unzOpenCurrentFile(zip_file_);
359 if (open_result != UNZ_OK)
360 return false;
361
432 // The original_size() is the best hint for the real size, so it saves 362 // The original_size() is the best hint for the real size, so it saves
433 // doing reallocations for the common case when the uncompressed size is 363 // doing reallocations for the common case when the uncompressed size is
434 // correct. However, we need to assume that the uncompressed size could be 364 // correct. However, we need to assume that the uncompressed size could be
435 // incorrect therefore this function needs to read as much data as possible. 365 // incorrect therefore this function needs to read as much data as possible.
436 std::string contents; 366 std::string contents;
437 contents.reserve(static_cast<size_t>(std::min( 367 contents.reserve(static_cast<size_t>(std::min(
438 static_cast<int64>(max_read_bytes), 368 static_cast<int64>(max_read_bytes),
439 current_entry_info()->original_size()))); 369 current_entry_info()->original_size())));
440 370
441 StringWriterDelegate writer(max_read_bytes, &contents); 371 bool success = true; // This becomes false when something bad happens.
442 if (!ExtractCurrentEntry(&writer)) 372 char buf[internal::kZipBufSize];
443 return false; 373 while (true) {
444 output->swap(contents); 374 const int num_bytes_read = unzReadCurrentFile(zip_file_, buf,
445 return true; 375 internal::kZipBufSize);
376 if (num_bytes_read == 0) {
377 // Reached the end of the file.
378 break;
379 } else if (num_bytes_read < 0) {
380 // If num_bytes_read < 0, then it's a specific UNZ_* error code.
381 success = false;
382 break;
383 } else if (num_bytes_read > 0) {
384 if (contents.size() + num_bytes_read > max_read_bytes) {
385 success = false;
386 break;
387 }
388 contents.append(buf, num_bytes_read);
389 }
390 }
391
392 unzCloseCurrentFile(zip_file_);
393 if (success)
394 output->swap(contents);
395
396 return success;
446 } 397 }
447 398
448 bool ZipReader::OpenInternal() { 399 bool ZipReader::OpenInternal() {
449 DCHECK(zip_file_); 400 DCHECK(zip_file_);
450 401
451 unz_global_info zip_info = {}; // Zero-clear. 402 unz_global_info zip_info = {}; // Zero-clear.
452 if (unzGetGlobalInfo(zip_file_, &zip_info) != UNZ_OK) { 403 if (unzGetGlobalInfo(zip_file_, &zip_info) != UNZ_OK) {
453 return false; 404 return false;
454 } 405 }
455 num_entries_ = zip_info.number_entry; 406 num_entries_ = zip_info.number_entry;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 weak_ptr_factory_.GetWeakPtr(), 454 weak_ptr_factory_.GetWeakPtr(),
504 Passed(output_file.Pass()), 455 Passed(output_file.Pass()),
505 success_callback, 456 success_callback,
506 failure_callback, 457 failure_callback,
507 progress_callback, 458 progress_callback,
508 current_progress)); 459 current_progress));
509 460
510 } 461 }
511 } 462 }
512 463
513 // FileWriterDelegate ----------------------------------------------------------
514
515 FileWriterDelegate::FileWriterDelegate(base::File* file)
516 : file_(file),
517 file_length_(0) {
518 }
519
520 FileWriterDelegate::~FileWriterDelegate() {
521 #if !defined(NDEBUG)
522 const bool success =
523 #endif
524 file_->SetLength(file_length_);
525 DPLOG_IF(ERROR, !success) << "Failed updating length of written file";
526 }
527
528 bool FileWriterDelegate::PrepareOutput() {
529 return file_->Seek(base::File::FROM_BEGIN, 0) >= 0;
530 }
531
532 bool FileWriterDelegate::WriteBytes(const char* data, int num_bytes) {
533 int bytes_written = file_->WriteAtCurrentPos(data, num_bytes);
534 if (bytes_written > 0)
535 file_length_ += bytes_written;
536 return bytes_written == num_bytes;
537 }
538 464
539 } // namespace zip 465 } // namespace zip
OLDNEW
« no previous file with comments | « third_party/zlib/google/zip_reader.h ('k') | third_party/zlib/google/zip_reader_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698