1 // Copyright 2011 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef THIRD_PARTY_ZLIB_GOOGLE_ZIP_H_ 6 #define THIRD_PARTY_ZLIB_GOOGLE_ZIP_H_ 7 8 #include <cstdint> 9 #include <ostream> 10 #include <utility> 11 #include <vector> 12 13 #include "base/containers/span.h" 14 #include "base/files/file_path.h" 15 #include "base/files/platform_file.h" 16 #include "base/functional/callback.h" 17 #include "base/time/time.h" 18 #include "build/build_config.h" 19 20 namespace base { 21 class File; 22 } 23 24 namespace zip { 25 26 class WriterDelegate; 27 28 // Paths passed as span to avoid copying them. 29 using Paths = base::span<const base::FilePath>; 30 31 // Abstraction for file access operation required by Zip(). 32 // 33 // Can be passed to the ZipParams for providing custom access to the files, 34 // for example over IPC. 35 // 36 // All parameters paths are expected to be relative to the source directory. 37 class FileAccessor { 38 public: 39 virtual ~FileAccessor() = default; 40 41 struct Info { 42 bool is_directory = false; 43 base::Time last_modified; 44 }; 45 46 // Opens files specified in |paths|. 47 // Directories should be mapped to invalid files. 48 virtual bool Open(Paths paths, std::vector<base::File>* files) = 0; 49 50 // Lists contents of a directory at |path|. 51 virtual bool List(const base::FilePath& path, 52 std::vector<base::FilePath>* files, 53 std::vector<base::FilePath>* subdirs) = 0; 54 55 // Gets info about a file or directory. 56 virtual bool GetInfo(const base::FilePath& path, Info* info) = 0; 57 }; 58 59 // Progress of a ZIP creation operation. 60 struct Progress { 61 // Total number of bytes read from files getting zipped so far. 62 std::int64_t bytes = 0; 63 64 // Number of file entries added to the ZIP so far. 65 // A file entry is added after its bytes have been processed. 66 int files = 0; 67 68 // Number of directory entries added to the ZIP so far. 69 // A directory entry is added before items in it. 70 int directories = 0; 71 72 // Number of errors encountered so far (files that cannot be opened, 73 // directories that cannot be listed). 74 int errors = 0; 75 }; 76 77 // Prints Progress to output stream. 78 std::ostream& operator<<(std::ostream& out, const Progress& progress); 79 80 // Callback reporting the progress of a ZIP creation operation. 81 // 82 // This callback returns a boolean indicating whether the ZIP creation operation 83 // should continue. If it returns false once, then the ZIP creation operation is 84 // immediately cancelled and the callback won't be called again. 85 using ProgressCallback = base::RepeatingCallback<bool(const Progress&)>; 86 87 using FilterCallback = base::RepeatingCallback<bool(const base::FilePath&)>; 88 89 // ZIP creation parameters and options. 90 struct ZipParams { 91 // Source directory. Ignored if |file_accessor| is set. 92 base::FilePath src_dir; 93 94 // Abstraction around file system access used to read files. 95 // If left null, an implementation that accesses files directly is used. 96 FileAccessor* file_accessor = nullptr; // Not owned 97 98 // Destination file path. 99 // Either dest_file or dest_fd should be set, but not both. 100 base::FilePath dest_file; 101 102 #if defined(OS_POSIX) || defined(OS_FUCHSIA) 103 // Destination file passed a file descriptor. 104 // Either dest_file or dest_fd should be set, but not both. 105 int dest_fd = base::kInvalidPlatformFile; 106 #endif 107 108 // The relative paths to the files and directories that should be included in 109 // the ZIP file. If this is empty, the whole contents of |src_dir| are 110 // included. 111 // 112 // These paths must be relative to |src_dir| and will be used as the file 113 // names in the created ZIP file. All files must be under |src_dir| in the 114 // file system hierarchy. 115 // 116 // All the paths in |src_files| are included in the created ZIP file, 117 // irrespective of |include_hidden_files| and |filter_callback|. 118 Paths src_files; 119 120 // Filter used to exclude files from the ZIP file. This is only taken in 121 // account when recursively adding subdirectory contents. 122 FilterCallback filter_callback; 123 124 // Optional progress reporting callback. 125 ProgressCallback progress_callback; 126 127 // Progress reporting period. The final callback is always called when the ZIP 128 // creation operation completes. 129 base::TimeDelta progress_period; 130 131 // Should add hidden files? This is only taken in account when recursively 132 // adding subdirectory contents. 133 bool include_hidden_files = true; 134 135 // Should recursively add subdirectory contents? 136 bool recursive = false; 137 138 // Should ignore errors when discovering files and zipping them? 139 bool continue_on_error = false; 140 }; 141 142 // Zip files specified into a ZIP archives. The source files and ZIP destination 143 // files (as well as other settings) are specified in |params|. 144 bool Zip(const ZipParams& params); 145 146 // Zip the contents of src_dir into dest_file. src_path must be a directory. 147 // An entry will *not* be created in the zip for the root folder -- children 148 // of src_dir will be at the root level of the created zip. For each file in 149 // src_dir, include it only if the callback |filter_cb| returns true. Otherwise 150 // omit it. 151 bool ZipWithFilterCallback(const base::FilePath& src_dir, 152 const base::FilePath& dest_file, 153 FilterCallback filter_cb); 154 155 // Convenience method for callers who don't need to set up the filter callback. 156 // If |include_hidden_files| is true, files starting with "." are included. 157 // Otherwise they are omitted. 158 bool Zip(const base::FilePath& src_dir, 159 const base::FilePath& dest_file, 160 bool include_hidden_files); 161 162 #if defined(OS_POSIX) || defined(OS_FUCHSIA) 163 // Zips files listed in |src_relative_paths| to destination specified by file 164 // descriptor |dest_fd|, without taking ownership of |dest_fd|. The paths listed 165 // in |src_relative_paths| are relative to the |src_dir| and will be used as the 166 // file names in the created zip file. All source paths must be under |src_dir| 167 // in the file system hierarchy. 168 bool ZipFiles(const base::FilePath& src_dir, 169 Paths src_relative_paths, 170 int dest_fd); 171 #endif // defined(OS_POSIX) || defined(OS_FUCHSIA) 172 173 // Callback reporting the number of bytes written during Unzip. 174 using UnzipProgressCallback = base::RepeatingCallback<void(uint64_t bytes)>; 175 176 // Options of the Unzip function, with valid default values. 177 struct UnzipOptions { 178 // Encoding of entry paths in the ZIP archive. By default, paths are assumed 179 // to be in UTF-8. 180 std::string encoding; 181 182 // Only extract the entries for which |filter_cb| returns true. By default, 183 // everything gets extracted. 184 FilterCallback filter; 185 186 // Callback to report bytes extracted from the ZIP. 187 UnzipProgressCallback progress; 188 189 // Password to decrypt the encrypted files. 190 std::string password; 191 192 // Should ignore errors when extracting files? 193 bool continue_on_error = false; 194 }; 195 196 typedef base::RepeatingCallback<std::unique_ptr<WriterDelegate>( 197 const base::FilePath&)> 198 WriterFactory; 199 200 typedef base::RepeatingCallback<bool(const base::FilePath&)> DirectoryCreator; 201 202 // Unzips the contents of |zip_file|, using the writers provided by 203 // |writer_factory|. 204 bool Unzip(const base::PlatformFile& zip_file, 205 WriterFactory writer_factory, 206 DirectoryCreator directory_creator, 207 UnzipOptions options = {}); 208 209 // Unzips the contents of |zip_file| into |dest_dir|. 210 // This function does not overwrite any existing file. 211 // A filename collision will result in an error. 212 // Therefore, |dest_dir| should initially be an empty directory. 213 bool Unzip(const base::FilePath& zip_file, 214 const base::FilePath& dest_dir, 215 UnzipOptions options = {}); 216 217 } // namespace zip 218 219 #endif // THIRD_PARTY_ZLIB_GOOGLE_ZIP_H_ 220