Index: third_party/zlib/google/zip.cc |
diff --git a/third_party/zlib/google/zip.cc b/third_party/zlib/google/zip.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f0180e533c8722a75f0da42352208a48fbf2c729 |
--- /dev/null |
+++ b/third_party/zlib/google/zip.cc |
@@ -0,0 +1,205 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "third_party/zlib/google/zip.h" |
+ |
+#include <string> |
+#include <vector> |
+ |
+#include "base/bind.h" |
+#include "base/files/file.h" |
+#include "base/files/file_enumerator.h" |
+#include "base/logging.h" |
+#include "base/strings/string16.h" |
+#include "base/strings/string_util.h" |
+#include "build/build_config.h" |
+#include "third_party/zlib/google/zip_internal.h" |
+#include "third_party/zlib/google/zip_reader.h" |
+ |
+#if defined(USE_SYSTEM_MINIZIP) |
+#include <minizip/unzip.h> |
+#include <minizip/zip.h> |
+#else |
+#include "third_party/zlib/contrib/minizip/unzip.h" |
+#include "third_party/zlib/contrib/minizip/zip.h" |
+#endif |
+ |
+namespace { |
+ |
+bool AddFileToZip(zipFile zip_file, const base::FilePath& src_dir) { |
+ base::File file(src_dir, base::File::FLAG_OPEN | base::File::FLAG_READ); |
+ if (!file.IsValid()) { |
+ DLOG(ERROR) << "Could not open file for path " << src_dir.value(); |
+ return false; |
+ } |
+ |
+ int num_bytes; |
+ char buf[zip::internal::kZipBufSize]; |
+ do { |
+ num_bytes = file.ReadAtCurrentPos(buf, zip::internal::kZipBufSize); |
+ if (num_bytes > 0) { |
+ if (ZIP_OK != zipWriteInFileInZip(zip_file, buf, num_bytes)) { |
+ DLOG(ERROR) << "Could not write data to zip for path " |
+ << src_dir.value(); |
+ return false; |
+ } |
+ } |
+ } while (num_bytes > 0); |
+ |
+ return true; |
+} |
+ |
+bool AddEntryToZip(zipFile zip_file, const base::FilePath& path, |
+ const base::FilePath& root_path) { |
+ base::FilePath relative_path; |
+ bool result = root_path.AppendRelativePath(path, &relative_path); |
+ DCHECK(result); |
+ std::string str_path = relative_path.AsUTF8Unsafe(); |
+#if defined(OS_WIN) |
+ base::ReplaceSubstringsAfterOffset(&str_path, 0u, "\\", "/"); |
+#endif |
+ |
+ bool is_directory = base::DirectoryExists(path); |
+ if (is_directory) |
+ str_path += "/"; |
+ |
+ zip_fileinfo file_info = zip::internal::GetFileInfoForZipping(path); |
+ if (!zip::internal::ZipOpenNewFileInZip(zip_file, str_path, &file_info)) |
+ return false; |
+ |
+ bool success = true; |
+ if (!is_directory) { |
+ success = AddFileToZip(zip_file, path); |
+ } |
+ |
+ if (ZIP_OK != zipCloseFileInZip(zip_file)) { |
+ DLOG(ERROR) << "Could not close zip file entry " << str_path; |
+ return false; |
+ } |
+ |
+ return success; |
+} |
+ |
+bool ExcludeNoFilesFilter(const base::FilePath& file_path) { |
+ return true; |
+} |
+ |
+bool ExcludeHiddenFilesFilter(const base::FilePath& file_path) { |
+ return file_path.BaseName().value()[0] != '.'; |
+} |
+ |
+} // namespace |
+ |
+namespace zip { |
+ |
+bool Unzip(const base::FilePath& src_file, const base::FilePath& dest_dir) { |
+ ZipReader reader; |
+ if (!reader.Open(src_file)) { |
+ DLOG(WARNING) << "Failed to open " << src_file.value(); |
+ return false; |
+ } |
+ while (reader.HasMore()) { |
+ if (!reader.OpenCurrentEntryInZip()) { |
+ DLOG(WARNING) << "Failed to open the current file in zip"; |
+ return false; |
+ } |
+ if (reader.current_entry_info()->is_unsafe()) { |
+ DLOG(WARNING) << "Found an unsafe file in zip " |
+ << reader.current_entry_info()->file_path().value(); |
+ return false; |
+ } |
+ if (!reader.ExtractCurrentEntryIntoDirectory(dest_dir)) { |
+ DLOG(WARNING) << "Failed to extract " |
+ << reader.current_entry_info()->file_path().value(); |
+ return false; |
+ } |
+ if (!reader.AdvanceToNextEntry()) { |
+ DLOG(WARNING) << "Failed to advance to the next file"; |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
+bool ZipWithFilterCallback(const base::FilePath& src_dir, |
+ const base::FilePath& dest_file, |
+ const FilterCallback& filter_cb) { |
+ DCHECK(base::DirectoryExists(src_dir)); |
+ |
+ zipFile zip_file = internal::OpenForZipping(dest_file.AsUTF8Unsafe(), |
+ APPEND_STATUS_CREATE); |
+ |
+ if (!zip_file) { |
+ DLOG(WARNING) << "couldn't create file " << dest_file.value(); |
+ return false; |
+ } |
+ |
+ bool success = true; |
+ base::FileEnumerator file_enumerator(src_dir, true /* recursive */, |
+ base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); |
+ for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); |
+ path = file_enumerator.Next()) { |
+ if (!filter_cb.Run(path)) { |
+ continue; |
+ } |
+ |
+ if (!AddEntryToZip(zip_file, path, src_dir)) { |
+ success = false; |
+ break; |
+ } |
+ } |
+ |
+ if (ZIP_OK != zipClose(zip_file, NULL)) { |
+ DLOG(ERROR) << "Error closing zip file " << dest_file.value(); |
+ return false; |
+ } |
+ |
+ return success; |
+} |
+ |
+bool Zip(const base::FilePath& src_dir, const base::FilePath& dest_file, |
+ bool include_hidden_files) { |
+ if (include_hidden_files) { |
+ return ZipWithFilterCallback( |
+ src_dir, dest_file, base::Bind(&ExcludeNoFilesFilter)); |
+ } else { |
+ return ZipWithFilterCallback( |
+ src_dir, dest_file, base::Bind(&ExcludeHiddenFilesFilter)); |
+ } |
+} |
+ |
+#if defined(OS_POSIX) |
+bool ZipFiles(const base::FilePath& src_dir, |
+ const std::vector<base::FilePath>& src_relative_paths, |
+ int dest_fd) { |
+ DCHECK(base::DirectoryExists(src_dir)); |
+ zipFile zip_file = internal::OpenFdForZipping(dest_fd, APPEND_STATUS_CREATE); |
+ |
+ if (!zip_file) { |
+ DLOG(ERROR) << "couldn't create file for fd " << dest_fd; |
+ return false; |
+ } |
+ |
+ bool success = true; |
+ for (std::vector<base::FilePath>::const_iterator iter = |
+ src_relative_paths.begin(); |
+ iter != src_relative_paths.end(); ++iter) { |
+ const base::FilePath& path = src_dir.Append(*iter); |
+ if (!AddEntryToZip(zip_file, path, src_dir)) { |
+ // TODO(hshi): clean up the partial zip file when error occurs. |
+ success = false; |
+ break; |
+ } |
+ } |
+ |
+ if (ZIP_OK != zipClose(zip_file, NULL)) { |
+ DLOG(ERROR) << "Error closing zip file for fd " << dest_fd; |
+ success = false; |
+ } |
+ |
+ return success; |
+} |
+#endif // defined(OS_POSIX) |
+ |
+} // namespace zip |