12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/zip.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/file_util.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/zip_internal.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/zip_reader.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/file_stream.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_SYSTEM_MINIZIP)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <minizip/unzip.h>
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <minizip/zip.h>
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/zlib/contrib/minizip/unzip.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/zlib/contrib/minizip/zip.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AddFileToZip(zipFile zip_file, const base::FilePath& src_dir) {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::FileStream stream(NULL);
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (stream.OpenSync(src_dir, flags) != 0) {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(ERROR) << "Could not open stream for path "
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                << src_dir.value();
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int num_bytes;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char buf[zip::internal::kZipBufSize];
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  do {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    num_bytes = stream.ReadSync(buf, zip::internal::kZipBufSize);
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (num_bytes > 0) {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (ZIP_OK != zipWriteInFileInZip(zip_file, buf, num_bytes)) {
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DLOG(ERROR) << "Could not write data to zip for path "
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    << src_dir.value();
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return false;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } while (num_bytes > 0);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AddEntryToZip(zipFile zip_file, const base::FilePath& path,
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   const base::FilePath& root_path) {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string str_path =
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      path.AsUTF8Unsafe().substr(root_path.value().length() + 1);
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReplaceSubstringsAfterOffset(&str_path, 0u, "\\", "/");
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  bool is_directory = base::DirectoryExists(path);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_directory)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    str_path += "/";
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ZIP_OK != zipOpenNewFileInZip(
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      zip_file, str_path.c_str(),
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NULL, NULL, 0u, NULL, 0u, NULL,  // file info, extrafield local, length,
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       // extrafield global, length, comment
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Z_DEFLATED, Z_DEFAULT_COMPRESSION)) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(ERROR) << "Could not open zip file entry " << str_path;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool success = true;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!is_directory) {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    success = AddFileToZip(zip_file, path);
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ZIP_OK != zipCloseFileInZip(zip_file)) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(ERROR) << "Could not close zip file entry " << str_path;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return success;
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ExcludeNoFilesFilter(const base::FilePath& file_path) {
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ExcludeHiddenFilesFilter(const base::FilePath& file_path) {
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return file_path.BaseName().value()[0] != '.';
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace zip {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Unzip(const base::FilePath& src_file, const base::FilePath& dest_dir) {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ZipReader reader;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!reader.Open(src_file)) {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(WARNING) << "Failed to open " << src_file.value();
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (reader.HasMore()) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.OpenCurrentEntryInZip()) {
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DLOG(WARNING) << "Failed to open the current file in zip";
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (reader.current_entry_info()->is_unsafe()) {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DLOG(WARNING) << "Found an unsafe file in zip "
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    << reader.current_entry_info()->file_path().value();
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.ExtractCurrentEntryIntoDirectory(dest_dir)) {
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DLOG(WARNING) << "Failed to extract "
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    << reader.current_entry_info()->file_path().value();
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.AdvanceToNextEntry()) {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DLOG(WARNING) << "Failed to advance to the next file";
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ZipWithFilterCallback(const base::FilePath& src_dir,
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const base::FilePath& dest_file,
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const FilterCallback& filter_cb) {
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(base::DirectoryExists(src_dir));
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  zipFile zip_file = internal::OpenForZipping(dest_file.AsUTF8Unsafe(),
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              APPEND_STATUS_CREATE);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!zip_file) {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(WARNING) << "couldn't create file " << dest_file.value();
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool success = true;
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::FileEnumerator file_enumerator(src_dir, true /* recursive */,
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (base::FilePath path = file_enumerator.Next(); !path.value().empty();
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       path = file_enumerator.Next()) {
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!filter_cb.Run(path)) {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!AddEntryToZip(zip_file, path, src_dir)) {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      success = false;
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ZIP_OK != zipClose(zip_file, NULL)) {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(ERROR) << "Error closing zip file " << dest_file.value();
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return success;
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Zip(const base::FilePath& src_dir, const base::FilePath& dest_file,
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         bool include_hidden_files) {
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (include_hidden_files) {
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ZipWithFilterCallback(
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        src_dir, dest_file, base::Bind(&ExcludeNoFilesFilter));
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ZipWithFilterCallback(
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        src_dir, dest_file, base::Bind(&ExcludeHiddenFilesFilter));
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_POSIX)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ZipFiles(const base::FilePath& src_dir,
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              const std::vector<base::FilePath>& src_relative_paths,
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              int dest_fd) {
1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(base::DirectoryExists(src_dir));
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  zipFile zip_file = internal::OpenFdForZipping(dest_fd, APPEND_STATUS_CREATE);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!zip_file) {
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(ERROR) << "couldn't create file for fd " << dest_fd;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool success = true;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::vector<base::FilePath>::const_iterator iter =
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           src_relative_paths.begin();
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      iter != src_relative_paths.end(); ++iter) {
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& path = src_dir.Append(*iter);
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!AddEntryToZip(zip_file, path, src_dir)) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // TODO(hshi): clean up the partial zip file when error occurs.
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      success = false;
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ZIP_OK != zipClose(zip_file, NULL)) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(ERROR) << "Error closing zip file for fd " << dest_fd;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    success = false;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return success;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(OS_POSIX)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace zip
208