Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/files/file.h" | 10 #include "base/files/file.h" |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 const int result = unzLocateFile(zip_file_, | 282 const int result = unzLocateFile(zip_file_, |
| 283 path_in_zip.AsUTF8Unsafe().c_str(), | 283 path_in_zip.AsUTF8Unsafe().c_str(), |
| 284 kDefaultCaseSensivityOfOS); | 284 kDefaultCaseSensivityOfOS); |
| 285 if (result != UNZ_OK) | 285 if (result != UNZ_OK) |
| 286 return false; | 286 return false; |
| 287 | 287 |
| 288 // Then Open the entry. | 288 // Then Open the entry. |
| 289 return OpenCurrentEntryInZip(); | 289 return OpenCurrentEntryInZip(); |
| 290 } | 290 } |
| 291 | 291 |
| 292 bool ZipReader::ExtractCurrentEntry(WriterDelegate* delegate) const { | 292 bool ZipReader::ExtractCurrentEntry(WriterDelegate* delegate, |
| 293 uint64_t num_bytes_to_extract) const { | |
| 293 DCHECK(zip_file_); | 294 DCHECK(zip_file_); |
| 294 | 295 |
| 295 const int open_result = unzOpenCurrentFile(zip_file_); | 296 const int open_result = unzOpenCurrentFile(zip_file_); |
| 296 if (open_result != UNZ_OK) | 297 if (open_result != UNZ_OK) |
| 297 return false; | 298 return false; |
| 298 | 299 |
| 299 if (!delegate->PrepareOutput()) | 300 if (!delegate->PrepareOutput()) |
| 300 return false; | 301 return false; |
| 302 bool entire_file_extracted = false; | |
| 303 std::unique_ptr<char[]> buf(new char[internal::kZipBufSize]); | |
| 304 uint64_t total_num_bytes_extracted = 0; | |
| 301 | 305 |
| 302 bool success = true; // This becomes false when something bad happens. | |
| 303 std::unique_ptr<char[]> buf(new char[internal::kZipBufSize]); | |
| 304 while (true) { | 306 while (true) { |
| 305 const int num_bytes_read = unzReadCurrentFile(zip_file_, buf.get(), | 307 const int num_bytes_read = |
| 306 internal::kZipBufSize); | 308 unzReadCurrentFile(zip_file_, buf.get(), internal::kZipBufSize); |
| 309 | |
| 307 if (num_bytes_read == 0) { | 310 if (num_bytes_read == 0) { |
| 308 // Reached the end of the file. | 311 entire_file_extracted = true; |
| 309 break; | 312 break; |
| 310 } else if (num_bytes_read < 0) { | 313 } else if (num_bytes_read < 0) { |
| 311 // If num_bytes_read < 0, then it's a specific UNZ_* error code. | 314 // If num_bytes_read < 0, then it's a specific UNZ_* error code. |
| 312 success = false; | |
| 313 break; | 315 break; |
| 314 } else if (num_bytes_read > 0) { | 316 } else if (num_bytes_read > 0) { |
| 315 // Some data is read. | 317 // Some data is read. |
| 316 if (!delegate->WriteBytes(buf.get(), num_bytes_read)) { | 318 auto unread_bytes = base::CheckedNumeric<uint64_t>(num_bytes_to_extract) - |
| 317 success = false; | 319 total_num_bytes_extracted; |
| 320 uint64_t num_bytes_to_write = | |
| 321 std::min<uint64_t>(unread_bytes.ValueOrDie(), | |
| 322 base::checked_cast<uint64_t>(num_bytes_read)); | |
| 323 total_num_bytes_extracted += num_bytes_to_write; | |
| 324 if (!delegate->WriteBytes(buf.get(), num_bytes_to_write) || | |
| 325 num_bytes_to_extract == total_num_bytes_extracted) { | |
| 326 // Ensures function returns true if the entire file has been read. | |
| 327 if (num_bytes_to_write == | |
| 328 base::checked_cast<uint64_t>(num_bytes_read) && | |
| 329 unzReadCurrentFile(zip_file_, buf.get(), 1) == 0) { | |
|
satorux1
2017/07/27 23:18:10
I thought we could get rid of the call to unzReadC
mortonm
2017/07/31 18:13:04
Yeah, I think I originally wrote the function this
satorux1
2017/08/01 08:01:08
Ah you are right. Sorry for missing that point.
mortonm
2017/08/01 16:16:46
Done.
| |
| 330 entire_file_extracted = true; | |
| 331 } | |
| 318 break; | 332 break; |
| 319 } | 333 } |
| 320 } | 334 } |
| 321 } | 335 } |
| 322 | 336 |
| 323 unzCloseCurrentFile(zip_file_); | 337 unzCloseCurrentFile(zip_file_); |
| 324 | 338 |
| 325 return success; | 339 return entire_file_extracted; |
| 326 } | 340 } |
| 327 | 341 |
| 328 bool ZipReader::ExtractCurrentEntryToFilePath( | 342 bool ZipReader::ExtractCurrentEntryToFilePath( |
| 329 const base::FilePath& output_file_path) const { | 343 const base::FilePath& output_file_path) const { |
| 330 DCHECK(zip_file_); | 344 DCHECK(zip_file_); |
| 331 | 345 |
| 332 // If this is a directory, just create it and return. | 346 // If this is a directory, just create it and return. |
| 333 if (current_entry_info()->is_directory()) | 347 if (current_entry_info()->is_directory()) |
| 334 return base::CreateDirectory(output_file_path); | 348 return base::CreateDirectory(output_file_path); |
| 335 | 349 |
| 336 bool success = false; | 350 bool success = false; |
| 337 { | 351 { |
| 338 FilePathWriterDelegate writer(output_file_path); | 352 FilePathWriterDelegate writer(output_file_path); |
| 339 success = ExtractCurrentEntry(&writer); | 353 success = |
| 354 ExtractCurrentEntry(&writer, std::numeric_limits<uint64_t>::max()); | |
| 340 } | 355 } |
| 341 | 356 |
| 342 if (success && | 357 if (success && |
| 343 current_entry_info()->last_modified() != base::Time::UnixEpoch()) { | 358 current_entry_info()->last_modified() != base::Time::UnixEpoch()) { |
| 344 base::TouchFile(output_file_path, | 359 base::TouchFile(output_file_path, |
| 345 base::Time::Now(), | 360 base::Time::Now(), |
| 346 current_entry_info()->last_modified()); | 361 current_entry_info()->last_modified()); |
| 347 } | 362 } |
| 348 | 363 |
| 349 return success; | 364 return success; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 409 | 424 |
| 410 bool ZipReader::ExtractCurrentEntryToFile(base::File* file) const { | 425 bool ZipReader::ExtractCurrentEntryToFile(base::File* file) const { |
| 411 DCHECK(zip_file_); | 426 DCHECK(zip_file_); |
| 412 | 427 |
| 413 // If this is a directory, there's nothing to extract to the file, so return | 428 // If this is a directory, there's nothing to extract to the file, so return |
| 414 // false. | 429 // false. |
| 415 if (current_entry_info()->is_directory()) | 430 if (current_entry_info()->is_directory()) |
| 416 return false; | 431 return false; |
| 417 | 432 |
| 418 FileWriterDelegate writer(file); | 433 FileWriterDelegate writer(file); |
| 419 return ExtractCurrentEntry(&writer); | 434 return ExtractCurrentEntry(&writer, std::numeric_limits<uint64_t>::max()); |
| 420 } | 435 } |
| 421 | 436 |
| 422 bool ZipReader::ExtractCurrentEntryToString(size_t max_read_bytes, | 437 bool ZipReader::ExtractCurrentEntryToString(uint64_t max_read_bytes, |
| 423 std::string* output) const { | 438 std::string* output) const { |
| 424 DCHECK(output); | 439 DCHECK(output); |
| 425 DCHECK(zip_file_); | 440 DCHECK(zip_file_); |
| 426 DCHECK_NE(0U, max_read_bytes); | 441 |
| 442 if (max_read_bytes == 0) { | |
| 443 output->clear(); | |
| 444 return true; | |
| 445 } | |
| 427 | 446 |
| 428 if (current_entry_info()->is_directory()) { | 447 if (current_entry_info()->is_directory()) { |
| 429 output->clear(); | 448 output->clear(); |
| 430 return true; | 449 return true; |
| 431 } | 450 } |
| 432 | 451 |
| 433 // The original_size() is the best hint for the real size, so it saves | 452 // The original_size() is the best hint for the real size, so it saves |
| 434 // doing reallocations for the common case when the uncompressed size is | 453 // doing reallocations for the common case when the uncompressed size is |
| 435 // correct. However, we need to assume that the uncompressed size could be | 454 // correct. However, we need to assume that the uncompressed size could be |
| 436 // incorrect therefore this function needs to read as much data as possible. | 455 // incorrect therefore this function needs to read as much data as possible. |
| 437 std::string contents; | 456 std::string contents; |
| 438 contents.reserve( | 457 contents.reserve( |
| 439 static_cast<size_t>(std::min(static_cast<int64_t>(max_read_bytes), | 458 static_cast<size_t>(std::min(base::checked_cast<int64_t>(max_read_bytes), |
| 440 current_entry_info()->original_size()))); | 459 current_entry_info()->original_size()))); |
| 441 | 460 |
| 442 StringWriterDelegate writer(max_read_bytes, &contents); | 461 StringWriterDelegate writer(max_read_bytes, &contents); |
| 443 if (!ExtractCurrentEntry(&writer)) | 462 if (!ExtractCurrentEntry(&writer, max_read_bytes)) { |
| 463 if (contents.length() < max_read_bytes) { | |
| 464 // There was an error in extracting entry. If ExtractCurrentEntry() | |
| 465 // returns false, the entire file was not read - in which case | |
| 466 // contents.length() should equal |max_read_bytes| unless an error | |
| 467 // occurred which caused extraction to be aborted. | |
| 468 output->clear(); | |
| 469 } else { | |
| 470 // |num_bytes| is less than the length of current entry. | |
| 471 output->swap(contents); | |
| 472 } | |
| 444 return false; | 473 return false; |
| 474 } | |
| 445 output->swap(contents); | 475 output->swap(contents); |
| 446 return true; | 476 return true; |
| 447 } | 477 } |
| 448 | 478 |
| 449 bool ZipReader::OpenInternal() { | 479 bool ZipReader::OpenInternal() { |
| 450 DCHECK(zip_file_); | 480 DCHECK(zip_file_); |
| 451 | 481 |
| 452 unz_global_info zip_info = {}; // Zero-clear. | 482 unz_global_info zip_info = {}; // Zero-clear. |
| 453 if (unzGetGlobalInfo(zip_file_, &zip_info) != UNZ_OK) { | 483 if (unzGetGlobalInfo(zip_file_, &zip_info) != UNZ_OK) { |
| 454 return false; | 484 return false; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 524 } | 554 } |
| 525 | 555 |
| 526 bool FileWriterDelegate::WriteBytes(const char* data, int num_bytes) { | 556 bool FileWriterDelegate::WriteBytes(const char* data, int num_bytes) { |
| 527 int bytes_written = file_->WriteAtCurrentPos(data, num_bytes); | 557 int bytes_written = file_->WriteAtCurrentPos(data, num_bytes); |
| 528 if (bytes_written > 0) | 558 if (bytes_written > 0) |
| 529 file_length_ += bytes_written; | 559 file_length_ += bytes_written; |
| 530 return bytes_written == num_bytes; | 560 return bytes_written == num_bytes; |
| 531 } | 561 } |
| 532 | 562 |
| 533 } // namespace zip | 563 } // namespace zip |
| OLD | NEW |