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

Unified Diff: third_party/zlib/google/zip_reader.cc

Issue 1014653002: Add ZipReader::ExtractCurrentEntry with a delegate interface. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix unused var error and add a new test 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/zlib/google/zip_reader.cc
diff --git a/third_party/zlib/google/zip_reader.cc b/third_party/zlib/google/zip_reader.cc
index a1dddfb85388a429ffc2e1308a4c39be57f87b5d..59d96da14263cbfb88d2230e8250396152e8b85c 100644
--- a/third_party/zlib/google/zip_reader.cc
+++ b/third_party/zlib/google/zip_reader.cc
@@ -23,6 +23,103 @@
namespace zip {
+namespace {
+
+// FilePathWriterDelegate ------------------------------------------------------
+
+// A writer delegate that writes a file at a given path.
+class FilePathWriterDelegate : public WriterDelegate {
+ public:
+ explicit FilePathWriterDelegate(const base::FilePath& output_file_path);
+ ~FilePathWriterDelegate() override;
+
+ // WriterDelegate methods:
+
+ // Creates the output file and any necessary intermediate directories.
+ bool PrepareOutput() override;
+
+ // Writes |num_bytes| bytes of |data| to the file, returning false if not all
+ // bytes could be written.
+ bool WriteBytes(const char* data, int num_bytes) override;
+
+ private:
+ base::FilePath output_file_path_;
+ base::File file_;
+
+ DISALLOW_COPY_AND_ASSIGN(FilePathWriterDelegate);
+};
+
+FilePathWriterDelegate::FilePathWriterDelegate(
+ const base::FilePath& output_file_path)
+ : output_file_path_(output_file_path) {
+}
+
+FilePathWriterDelegate::~FilePathWriterDelegate() {
+}
+
+bool FilePathWriterDelegate::PrepareOutput() {
+ // We can't rely on parent directory entries being specified in the
+ // zip, so we make sure they are created.
+ if (!base::CreateDirectory(output_file_path_.DirName()))
+ return false;
+
+ file_.Initialize(output_file_path_,
+ base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
+ return file_.IsValid();
+}
+
+bool FilePathWriterDelegate::WriteBytes(const char* data, int num_bytes) {
+ return num_bytes == file_.WriteAtCurrentPos(data, num_bytes);
+}
+
+
+// StringWriterDelegate --------------------------------------------------------
+
+// A writer delegate that writes no more than |max_read_bytes| to a given
+// std::string.
+class StringWriterDelegate : public WriterDelegate {
+ public:
+ StringWriterDelegate(size_t max_read_bytes, std::string* output);
+ ~StringWriterDelegate() override;
+
+ // WriterDelegate methods:
+
+ // Returns true.
+ bool PrepareOutput() override;
+
+ // Appends |num_bytes| bytes from |data| to the output string. Returns false
+ // if |num_bytes| will cause the string to exceed |max_read_bytes|.
+ bool WriteBytes(const char* data, int num_bytes) override;
+
+ private:
+ size_t max_read_bytes_;
+ std::string* output_;
+
+ DISALLOW_COPY_AND_ASSIGN(StringWriterDelegate);
+};
+
+StringWriterDelegate::StringWriterDelegate(size_t max_read_bytes,
+ std::string* output)
+ : max_read_bytes_(max_read_bytes),
+ output_(output) {
+}
+
+StringWriterDelegate::~StringWriterDelegate() {
+}
+
+bool StringWriterDelegate::PrepareOutput() {
+ return true;
+}
+
+bool StringWriterDelegate::WriteBytes(const char* data, int num_bytes) {
+ if (output_->size() + num_bytes > max_read_bytes_)
+ return false;
+ output_->append(data, num_bytes);
+ return true;
+}
+
+} // namespace
+
// TODO(satorux): The implementation assumes that file names in zip files
// are encoded in UTF-8. This is true for zip files created by Zip()
// function in zip.h, but not true for user-supplied random zip files.
@@ -187,33 +284,20 @@ bool ZipReader::LocateAndOpenEntry(const base::FilePath& path_in_zip) {
return OpenCurrentEntryInZip();
}
-bool ZipReader::ExtractCurrentEntryToFilePath(
- const base::FilePath& output_file_path) {
+bool ZipReader::ExtractCurrentEntry(WriterDelegate* delegate) const {
DCHECK(zip_file_);
- // If this is a directory, just create it and return.
- if (current_entry_info()->is_directory())
- return base::CreateDirectory(output_file_path);
-
const int open_result = unzOpenCurrentFile(zip_file_);
if (open_result != UNZ_OK)
return false;
- // We can't rely on parent directory entries being specified in the
- // zip, so we make sure they are created.
- base::FilePath output_dir_path = output_file_path.DirName();
- if (!base::CreateDirectory(output_dir_path))
- return false;
-
- base::File file(output_file_path,
- base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
- if (!file.IsValid())
+ if (!delegate->PrepareOutput())
return false;
bool success = true; // This becomes false when something bad happens.
+ scoped_ptr<char[]> buf(new char[internal::kZipBufSize]);
while (true) {
- char buf[internal::kZipBufSize];
- const int num_bytes_read = unzReadCurrentFile(zip_file_, buf,
+ const int num_bytes_read = unzReadCurrentFile(zip_file_, buf.get(),
internal::kZipBufSize);
if (num_bytes_read == 0) {
// Reached the end of the file.
@@ -223,21 +307,39 @@ bool ZipReader::ExtractCurrentEntryToFilePath(
success = false;
break;
} else if (num_bytes_read > 0) {
- // Some data is read. Write it to the output file.
- if (num_bytes_read != file.WriteAtCurrentPos(buf, num_bytes_read)) {
+ // Some data is read.
+ if (!delegate->WriteBytes(buf.get(), num_bytes_read)) {
success = false;
break;
}
}
}
- file.Close();
unzCloseCurrentFile(zip_file_);
- if (current_entry_info()->last_modified() != base::Time::UnixEpoch())
+ return success;
+}
+
+bool ZipReader::ExtractCurrentEntryToFilePath(
+ const base::FilePath& output_file_path) const {
+ DCHECK(zip_file_);
+
+ // If this is a directory, just create it and return.
+ if (current_entry_info()->is_directory())
+ return base::CreateDirectory(output_file_path);
+
+ bool success = false;
+ {
+ FilePathWriterDelegate writer(output_file_path);
+ success = ExtractCurrentEntry(&writer);
+ }
+
+ if (success &&
+ current_entry_info()->last_modified() != base::Time::UnixEpoch()) {
base::TouchFile(output_file_path,
base::Time::Now(),
current_entry_info()->last_modified());
+ }
return success;
}
@@ -296,7 +398,7 @@ void ZipReader::ExtractCurrentEntryToFilePathAsync(
}
bool ZipReader::ExtractCurrentEntryIntoDirectory(
- const base::FilePath& output_directory_path) {
+ const base::FilePath& output_directory_path) const {
DCHECK(current_entry_info_.get());
base::FilePath output_file_path = output_directory_path.Append(
@@ -304,61 +406,29 @@ bool ZipReader::ExtractCurrentEntryIntoDirectory(
return ExtractCurrentEntryToFilePath(output_file_path);
}
-#if defined(OS_POSIX)
-bool ZipReader::ExtractCurrentEntryToFd(const int fd) {
+bool ZipReader::ExtractCurrentEntryToFile(base::File* file) const {
DCHECK(zip_file_);
- // If this is a directory, there's nothing to extract to the file descriptor,
- // so return false.
+ // If this is a directory, there's nothing to extract to the file, so return
+ // false.
if (current_entry_info()->is_directory())
return false;
- const int open_result = unzOpenCurrentFile(zip_file_);
- if (open_result != UNZ_OK)
- return false;
-
- bool success = true; // This becomes false when something bad happens.
- while (true) {
- char buf[internal::kZipBufSize];
- const int num_bytes_read = unzReadCurrentFile(zip_file_, buf,
- internal::kZipBufSize);
- if (num_bytes_read == 0) {
- // Reached the end of the file.
- break;
- } else if (num_bytes_read < 0) {
- // If num_bytes_read < 0, then it's a specific UNZ_* error code.
- success = false;
- break;
- } else if (num_bytes_read > 0) {
- // Some data is read. Write it to the output file descriptor.
- if (!base::WriteFileDescriptor(fd, buf, num_bytes_read)) {
- success = false;
- break;
- }
- }
- }
-
- unzCloseCurrentFile(zip_file_);
- return success;
+ FileWriterDelegate writer(file);
+ return ExtractCurrentEntry(&writer);
}
-#endif // defined(OS_POSIX)
-bool ZipReader::ExtractCurrentEntryToString(
- size_t max_read_bytes,
- std::string* output) const {
+bool ZipReader::ExtractCurrentEntryToString(size_t max_read_bytes,
+ std::string* output) const {
DCHECK(output);
DCHECK(zip_file_);
- DCHECK(max_read_bytes != 0);
+ DCHECK_NE(0U, max_read_bytes);
if (current_entry_info()->is_directory()) {
output->clear();
return true;
}
- const int open_result = unzOpenCurrentFile(zip_file_);
- if (open_result != UNZ_OK)
- return false;
-
// The original_size() is the best hint for the real size, so it saves
// doing reallocations for the common case when the uncompressed size is
// correct. However, we need to assume that the uncompressed size could be
@@ -368,32 +438,11 @@ bool ZipReader::ExtractCurrentEntryToString(
static_cast<int64>(max_read_bytes),
current_entry_info()->original_size())));
- bool success = true; // This becomes false when something bad happens.
- char buf[internal::kZipBufSize];
- while (true) {
- const int num_bytes_read = unzReadCurrentFile(zip_file_, buf,
- internal::kZipBufSize);
- if (num_bytes_read == 0) {
- // Reached the end of the file.
- break;
- } else if (num_bytes_read < 0) {
- // If num_bytes_read < 0, then it's a specific UNZ_* error code.
- success = false;
- break;
- } else if (num_bytes_read > 0) {
- if (contents.size() + num_bytes_read > max_read_bytes) {
- success = false;
- break;
- }
- contents.append(buf, num_bytes_read);
- }
- }
-
- unzCloseCurrentFile(zip_file_);
- if (success)
- output->swap(contents);
-
- return success;
+ StringWriterDelegate writer(max_read_bytes, &contents);
+ if (!ExtractCurrentEntry(&writer))
+ return false;
+ output->swap(contents);
+ return true;
}
bool ZipReader::OpenInternal() {
@@ -461,5 +510,30 @@ void ZipReader::ExtractChunk(base::File output_file,
}
}
+// FileWriterDelegate ----------------------------------------------------------
+
+FileWriterDelegate::FileWriterDelegate(base::File* file)
+ : file_(file),
+ file_length_(0) {
+}
+
+FileWriterDelegate::~FileWriterDelegate() {
+#if !defined(NDEBUG)
+ const bool success =
+#endif
+ file_->SetLength(file_length_);
+ DPLOG_IF(ERROR, !success) << "Failed updating length of written file";
+}
+
+bool FileWriterDelegate::PrepareOutput() {
+ return file_->Seek(base::File::FROM_BEGIN, 0) >= 0;
+}
+
+bool FileWriterDelegate::WriteBytes(const char* data, int num_bytes) {
+ int bytes_written = file_->WriteAtCurrentPos(data, num_bytes);
+ if (bytes_written > 0)
+ file_length_ += bytes_written;
+ return bytes_written == num_bytes;
+}
} // namespace zip
« 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