1*86ee64e7SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors
2*86ee64e7SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*86ee64e7SAndroid Build Coastguard Worker // found in the LICENSE file.
4*86ee64e7SAndroid Build Coastguard Worker
5*86ee64e7SAndroid Build Coastguard Worker #include "third_party/zlib/google/zip_writer.h"
6*86ee64e7SAndroid Build Coastguard Worker
7*86ee64e7SAndroid Build Coastguard Worker #include <algorithm>
8*86ee64e7SAndroid Build Coastguard Worker
9*86ee64e7SAndroid Build Coastguard Worker #include "base/files/file.h"
10*86ee64e7SAndroid Build Coastguard Worker #include "base/logging.h"
11*86ee64e7SAndroid Build Coastguard Worker #include "base/strings/strcat.h"
12*86ee64e7SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
13*86ee64e7SAndroid Build Coastguard Worker #include "third_party/zlib/google/redact.h"
14*86ee64e7SAndroid Build Coastguard Worker #include "third_party/zlib/google/zip_internal.h"
15*86ee64e7SAndroid Build Coastguard Worker
16*86ee64e7SAndroid Build Coastguard Worker namespace zip {
17*86ee64e7SAndroid Build Coastguard Worker namespace internal {
18*86ee64e7SAndroid Build Coastguard Worker
ShouldContinue()19*86ee64e7SAndroid Build Coastguard Worker bool ZipWriter::ShouldContinue() {
20*86ee64e7SAndroid Build Coastguard Worker if (!progress_callback_)
21*86ee64e7SAndroid Build Coastguard Worker return true;
22*86ee64e7SAndroid Build Coastguard Worker
23*86ee64e7SAndroid Build Coastguard Worker const base::TimeTicks now = base::TimeTicks::Now();
24*86ee64e7SAndroid Build Coastguard Worker if (next_progress_report_time_ > now)
25*86ee64e7SAndroid Build Coastguard Worker return true;
26*86ee64e7SAndroid Build Coastguard Worker
27*86ee64e7SAndroid Build Coastguard Worker next_progress_report_time_ = now + progress_period_;
28*86ee64e7SAndroid Build Coastguard Worker if (progress_callback_.Run(progress_))
29*86ee64e7SAndroid Build Coastguard Worker return true;
30*86ee64e7SAndroid Build Coastguard Worker
31*86ee64e7SAndroid Build Coastguard Worker LOG(ERROR) << "Cancelling ZIP creation";
32*86ee64e7SAndroid Build Coastguard Worker return false;
33*86ee64e7SAndroid Build Coastguard Worker }
34*86ee64e7SAndroid Build Coastguard Worker
AddFileContent(const base::FilePath & path,base::File file)35*86ee64e7SAndroid Build Coastguard Worker bool ZipWriter::AddFileContent(const base::FilePath& path, base::File file) {
36*86ee64e7SAndroid Build Coastguard Worker char buf[zip::internal::kZipBufSize];
37*86ee64e7SAndroid Build Coastguard Worker
38*86ee64e7SAndroid Build Coastguard Worker while (ShouldContinue()) {
39*86ee64e7SAndroid Build Coastguard Worker const int num_bytes =
40*86ee64e7SAndroid Build Coastguard Worker file.ReadAtCurrentPos(buf, zip::internal::kZipBufSize);
41*86ee64e7SAndroid Build Coastguard Worker
42*86ee64e7SAndroid Build Coastguard Worker if (num_bytes < 0) {
43*86ee64e7SAndroid Build Coastguard Worker PLOG(ERROR) << "Cannot read file " << Redact(path);
44*86ee64e7SAndroid Build Coastguard Worker return false;
45*86ee64e7SAndroid Build Coastguard Worker }
46*86ee64e7SAndroid Build Coastguard Worker
47*86ee64e7SAndroid Build Coastguard Worker if (num_bytes == 0)
48*86ee64e7SAndroid Build Coastguard Worker return true;
49*86ee64e7SAndroid Build Coastguard Worker
50*86ee64e7SAndroid Build Coastguard Worker if (zipWriteInFileInZip(zip_file_, buf, num_bytes) != ZIP_OK) {
51*86ee64e7SAndroid Build Coastguard Worker PLOG(ERROR) << "Cannot write data from file " << Redact(path)
52*86ee64e7SAndroid Build Coastguard Worker << " to ZIP";
53*86ee64e7SAndroid Build Coastguard Worker return false;
54*86ee64e7SAndroid Build Coastguard Worker }
55*86ee64e7SAndroid Build Coastguard Worker
56*86ee64e7SAndroid Build Coastguard Worker progress_.bytes += num_bytes;
57*86ee64e7SAndroid Build Coastguard Worker }
58*86ee64e7SAndroid Build Coastguard Worker
59*86ee64e7SAndroid Build Coastguard Worker return false;
60*86ee64e7SAndroid Build Coastguard Worker }
61*86ee64e7SAndroid Build Coastguard Worker
OpenNewFileEntry(const base::FilePath & path,bool is_directory,base::Time last_modified)62*86ee64e7SAndroid Build Coastguard Worker bool ZipWriter::OpenNewFileEntry(const base::FilePath& path,
63*86ee64e7SAndroid Build Coastguard Worker bool is_directory,
64*86ee64e7SAndroid Build Coastguard Worker base::Time last_modified) {
65*86ee64e7SAndroid Build Coastguard Worker std::string str_path = path.AsUTF8Unsafe();
66*86ee64e7SAndroid Build Coastguard Worker
67*86ee64e7SAndroid Build Coastguard Worker #if defined(OS_WIN)
68*86ee64e7SAndroid Build Coastguard Worker base::ReplaceSubstringsAfterOffset(&str_path, 0u, "\\", "/");
69*86ee64e7SAndroid Build Coastguard Worker #endif
70*86ee64e7SAndroid Build Coastguard Worker
71*86ee64e7SAndroid Build Coastguard Worker Compression compression = kDeflated;
72*86ee64e7SAndroid Build Coastguard Worker
73*86ee64e7SAndroid Build Coastguard Worker if (is_directory) {
74*86ee64e7SAndroid Build Coastguard Worker str_path += "/";
75*86ee64e7SAndroid Build Coastguard Worker } else {
76*86ee64e7SAndroid Build Coastguard Worker compression = GetCompressionMethod(path);
77*86ee64e7SAndroid Build Coastguard Worker }
78*86ee64e7SAndroid Build Coastguard Worker
79*86ee64e7SAndroid Build Coastguard Worker return zip::internal::ZipOpenNewFileInZip(zip_file_, str_path, last_modified,
80*86ee64e7SAndroid Build Coastguard Worker compression);
81*86ee64e7SAndroid Build Coastguard Worker }
82*86ee64e7SAndroid Build Coastguard Worker
CloseNewFileEntry()83*86ee64e7SAndroid Build Coastguard Worker bool ZipWriter::CloseNewFileEntry() {
84*86ee64e7SAndroid Build Coastguard Worker return zipCloseFileInZip(zip_file_) == ZIP_OK;
85*86ee64e7SAndroid Build Coastguard Worker }
86*86ee64e7SAndroid Build Coastguard Worker
AddFileEntry(const base::FilePath & path,base::File file)87*86ee64e7SAndroid Build Coastguard Worker bool ZipWriter::AddFileEntry(const base::FilePath& path, base::File file) {
88*86ee64e7SAndroid Build Coastguard Worker base::File::Info info;
89*86ee64e7SAndroid Build Coastguard Worker if (!file.GetInfo(&info))
90*86ee64e7SAndroid Build Coastguard Worker return false;
91*86ee64e7SAndroid Build Coastguard Worker
92*86ee64e7SAndroid Build Coastguard Worker if (!OpenNewFileEntry(path, /*is_directory=*/false, info.last_modified))
93*86ee64e7SAndroid Build Coastguard Worker return false;
94*86ee64e7SAndroid Build Coastguard Worker
95*86ee64e7SAndroid Build Coastguard Worker if (!AddFileContent(path, std::move(file)))
96*86ee64e7SAndroid Build Coastguard Worker return false;
97*86ee64e7SAndroid Build Coastguard Worker
98*86ee64e7SAndroid Build Coastguard Worker progress_.files++;
99*86ee64e7SAndroid Build Coastguard Worker return CloseNewFileEntry();
100*86ee64e7SAndroid Build Coastguard Worker }
101*86ee64e7SAndroid Build Coastguard Worker
AddDirectoryEntry(const base::FilePath & path)102*86ee64e7SAndroid Build Coastguard Worker bool ZipWriter::AddDirectoryEntry(const base::FilePath& path) {
103*86ee64e7SAndroid Build Coastguard Worker FileAccessor::Info info;
104*86ee64e7SAndroid Build Coastguard Worker if (!file_accessor_->GetInfo(path, &info) || !info.is_directory) {
105*86ee64e7SAndroid Build Coastguard Worker LOG(ERROR) << "Not a directory: " << Redact(path);
106*86ee64e7SAndroid Build Coastguard Worker progress_.errors++;
107*86ee64e7SAndroid Build Coastguard Worker return continue_on_error_;
108*86ee64e7SAndroid Build Coastguard Worker }
109*86ee64e7SAndroid Build Coastguard Worker
110*86ee64e7SAndroid Build Coastguard Worker if (!OpenNewFileEntry(path, /*is_directory=*/true, info.last_modified))
111*86ee64e7SAndroid Build Coastguard Worker return false;
112*86ee64e7SAndroid Build Coastguard Worker
113*86ee64e7SAndroid Build Coastguard Worker if (!CloseNewFileEntry())
114*86ee64e7SAndroid Build Coastguard Worker return false;
115*86ee64e7SAndroid Build Coastguard Worker
116*86ee64e7SAndroid Build Coastguard Worker progress_.directories++;
117*86ee64e7SAndroid Build Coastguard Worker if (!ShouldContinue())
118*86ee64e7SAndroid Build Coastguard Worker return false;
119*86ee64e7SAndroid Build Coastguard Worker
120*86ee64e7SAndroid Build Coastguard Worker if (!recursive_)
121*86ee64e7SAndroid Build Coastguard Worker return true;
122*86ee64e7SAndroid Build Coastguard Worker
123*86ee64e7SAndroid Build Coastguard Worker return AddDirectoryContents(path);
124*86ee64e7SAndroid Build Coastguard Worker }
125*86ee64e7SAndroid Build Coastguard Worker
126*86ee64e7SAndroid Build Coastguard Worker #if defined(OS_POSIX) || defined(OS_FUCHSIA)
127*86ee64e7SAndroid Build Coastguard Worker // static
CreateWithFd(int zip_file_fd,FileAccessor * file_accessor)128*86ee64e7SAndroid Build Coastguard Worker std::unique_ptr<ZipWriter> ZipWriter::CreateWithFd(
129*86ee64e7SAndroid Build Coastguard Worker int zip_file_fd,
130*86ee64e7SAndroid Build Coastguard Worker FileAccessor* file_accessor) {
131*86ee64e7SAndroid Build Coastguard Worker DCHECK(zip_file_fd != base::kInvalidPlatformFile);
132*86ee64e7SAndroid Build Coastguard Worker zipFile zip_file =
133*86ee64e7SAndroid Build Coastguard Worker internal::OpenFdForZipping(zip_file_fd, APPEND_STATUS_CREATE);
134*86ee64e7SAndroid Build Coastguard Worker
135*86ee64e7SAndroid Build Coastguard Worker if (!zip_file) {
136*86ee64e7SAndroid Build Coastguard Worker DLOG(ERROR) << "Cannot create ZIP file for FD " << zip_file_fd;
137*86ee64e7SAndroid Build Coastguard Worker return nullptr;
138*86ee64e7SAndroid Build Coastguard Worker }
139*86ee64e7SAndroid Build Coastguard Worker
140*86ee64e7SAndroid Build Coastguard Worker return std::unique_ptr<ZipWriter>(new ZipWriter(zip_file, file_accessor));
141*86ee64e7SAndroid Build Coastguard Worker }
142*86ee64e7SAndroid Build Coastguard Worker #endif
143*86ee64e7SAndroid Build Coastguard Worker
144*86ee64e7SAndroid Build Coastguard Worker // static
Create(const base::FilePath & zip_file_path,FileAccessor * file_accessor)145*86ee64e7SAndroid Build Coastguard Worker std::unique_ptr<ZipWriter> ZipWriter::Create(
146*86ee64e7SAndroid Build Coastguard Worker const base::FilePath& zip_file_path,
147*86ee64e7SAndroid Build Coastguard Worker FileAccessor* file_accessor) {
148*86ee64e7SAndroid Build Coastguard Worker DCHECK(!zip_file_path.empty());
149*86ee64e7SAndroid Build Coastguard Worker zipFile zip_file = internal::OpenForZipping(zip_file_path.AsUTF8Unsafe(),
150*86ee64e7SAndroid Build Coastguard Worker APPEND_STATUS_CREATE);
151*86ee64e7SAndroid Build Coastguard Worker
152*86ee64e7SAndroid Build Coastguard Worker if (!zip_file) {
153*86ee64e7SAndroid Build Coastguard Worker PLOG(ERROR) << "Cannot create ZIP file " << Redact(zip_file_path);
154*86ee64e7SAndroid Build Coastguard Worker return nullptr;
155*86ee64e7SAndroid Build Coastguard Worker }
156*86ee64e7SAndroid Build Coastguard Worker
157*86ee64e7SAndroid Build Coastguard Worker return std::unique_ptr<ZipWriter>(new ZipWriter(zip_file, file_accessor));
158*86ee64e7SAndroid Build Coastguard Worker }
159*86ee64e7SAndroid Build Coastguard Worker
ZipWriter(zipFile zip_file,FileAccessor * file_accessor)160*86ee64e7SAndroid Build Coastguard Worker ZipWriter::ZipWriter(zipFile zip_file, FileAccessor* file_accessor)
161*86ee64e7SAndroid Build Coastguard Worker : zip_file_(zip_file), file_accessor_(file_accessor) {}
162*86ee64e7SAndroid Build Coastguard Worker
~ZipWriter()163*86ee64e7SAndroid Build Coastguard Worker ZipWriter::~ZipWriter() {
164*86ee64e7SAndroid Build Coastguard Worker if (zip_file_)
165*86ee64e7SAndroid Build Coastguard Worker zipClose(zip_file_, nullptr);
166*86ee64e7SAndroid Build Coastguard Worker }
167*86ee64e7SAndroid Build Coastguard Worker
Close()168*86ee64e7SAndroid Build Coastguard Worker bool ZipWriter::Close() {
169*86ee64e7SAndroid Build Coastguard Worker const bool success = zipClose(zip_file_, nullptr) == ZIP_OK;
170*86ee64e7SAndroid Build Coastguard Worker zip_file_ = nullptr;
171*86ee64e7SAndroid Build Coastguard Worker
172*86ee64e7SAndroid Build Coastguard Worker // Call the progress callback one last time with the final progress status.
173*86ee64e7SAndroid Build Coastguard Worker if (progress_callback_ && !progress_callback_.Run(progress_)) {
174*86ee64e7SAndroid Build Coastguard Worker LOG(ERROR) << "Cancelling ZIP creation at the end";
175*86ee64e7SAndroid Build Coastguard Worker return false;
176*86ee64e7SAndroid Build Coastguard Worker }
177*86ee64e7SAndroid Build Coastguard Worker
178*86ee64e7SAndroid Build Coastguard Worker return success;
179*86ee64e7SAndroid Build Coastguard Worker }
180*86ee64e7SAndroid Build Coastguard Worker
AddMixedEntries(Paths paths)181*86ee64e7SAndroid Build Coastguard Worker bool ZipWriter::AddMixedEntries(Paths paths) {
182*86ee64e7SAndroid Build Coastguard Worker // Pointers to directory paths in |paths|.
183*86ee64e7SAndroid Build Coastguard Worker std::vector<const base::FilePath*> directories;
184*86ee64e7SAndroid Build Coastguard Worker
185*86ee64e7SAndroid Build Coastguard Worker // Declared outside loop to reuse internal buffer.
186*86ee64e7SAndroid Build Coastguard Worker std::vector<base::File> files;
187*86ee64e7SAndroid Build Coastguard Worker
188*86ee64e7SAndroid Build Coastguard Worker // First pass. We don't know which paths are files and which ones are
189*86ee64e7SAndroid Build Coastguard Worker // directories, and we want to avoid making a call to file_accessor_ for each
190*86ee64e7SAndroid Build Coastguard Worker // path. Try to open all of the paths as files. We'll get invalid file
191*86ee64e7SAndroid Build Coastguard Worker // descriptors for directories, and we'll process these directories in the
192*86ee64e7SAndroid Build Coastguard Worker // second pass.
193*86ee64e7SAndroid Build Coastguard Worker while (!paths.empty()) {
194*86ee64e7SAndroid Build Coastguard Worker // Work with chunks of 50 paths at most.
195*86ee64e7SAndroid Build Coastguard Worker const size_t n = std::min<size_t>(paths.size(), 50);
196*86ee64e7SAndroid Build Coastguard Worker const Paths relative_paths = paths.subspan(0, n);
197*86ee64e7SAndroid Build Coastguard Worker paths = paths.subspan(n, paths.size() - n);
198*86ee64e7SAndroid Build Coastguard Worker
199*86ee64e7SAndroid Build Coastguard Worker files.clear();
200*86ee64e7SAndroid Build Coastguard Worker if (!file_accessor_->Open(relative_paths, &files) || files.size() != n)
201*86ee64e7SAndroid Build Coastguard Worker return false;
202*86ee64e7SAndroid Build Coastguard Worker
203*86ee64e7SAndroid Build Coastguard Worker for (size_t i = 0; i < n; i++) {
204*86ee64e7SAndroid Build Coastguard Worker const base::FilePath& relative_path = relative_paths[i];
205*86ee64e7SAndroid Build Coastguard Worker DCHECK(!relative_path.empty());
206*86ee64e7SAndroid Build Coastguard Worker base::File& file = files[i];
207*86ee64e7SAndroid Build Coastguard Worker
208*86ee64e7SAndroid Build Coastguard Worker if (file.IsValid()) {
209*86ee64e7SAndroid Build Coastguard Worker // It's a file.
210*86ee64e7SAndroid Build Coastguard Worker if (!AddFileEntry(relative_path, std::move(file)))
211*86ee64e7SAndroid Build Coastguard Worker return false;
212*86ee64e7SAndroid Build Coastguard Worker } else {
213*86ee64e7SAndroid Build Coastguard Worker // It's probably a directory. Remember its path for the second pass.
214*86ee64e7SAndroid Build Coastguard Worker directories.push_back(&relative_path);
215*86ee64e7SAndroid Build Coastguard Worker }
216*86ee64e7SAndroid Build Coastguard Worker }
217*86ee64e7SAndroid Build Coastguard Worker }
218*86ee64e7SAndroid Build Coastguard Worker
219*86ee64e7SAndroid Build Coastguard Worker // Second pass for directories discovered during the first pass.
220*86ee64e7SAndroid Build Coastguard Worker for (const base::FilePath* const path : directories) {
221*86ee64e7SAndroid Build Coastguard Worker DCHECK(path);
222*86ee64e7SAndroid Build Coastguard Worker if (!AddDirectoryEntry(*path))
223*86ee64e7SAndroid Build Coastguard Worker return false;
224*86ee64e7SAndroid Build Coastguard Worker }
225*86ee64e7SAndroid Build Coastguard Worker
226*86ee64e7SAndroid Build Coastguard Worker return true;
227*86ee64e7SAndroid Build Coastguard Worker }
228*86ee64e7SAndroid Build Coastguard Worker
AddFileEntries(Paths paths)229*86ee64e7SAndroid Build Coastguard Worker bool ZipWriter::AddFileEntries(Paths paths) {
230*86ee64e7SAndroid Build Coastguard Worker // Declared outside loop to reuse internal buffer.
231*86ee64e7SAndroid Build Coastguard Worker std::vector<base::File> files;
232*86ee64e7SAndroid Build Coastguard Worker
233*86ee64e7SAndroid Build Coastguard Worker while (!paths.empty()) {
234*86ee64e7SAndroid Build Coastguard Worker // Work with chunks of 50 paths at most.
235*86ee64e7SAndroid Build Coastguard Worker const size_t n = std::min<size_t>(paths.size(), 50);
236*86ee64e7SAndroid Build Coastguard Worker const Paths relative_paths = paths.subspan(0, n);
237*86ee64e7SAndroid Build Coastguard Worker paths = paths.subspan(n, paths.size() - n);
238*86ee64e7SAndroid Build Coastguard Worker
239*86ee64e7SAndroid Build Coastguard Worker DCHECK_EQ(relative_paths.size(), n);
240*86ee64e7SAndroid Build Coastguard Worker
241*86ee64e7SAndroid Build Coastguard Worker files.clear();
242*86ee64e7SAndroid Build Coastguard Worker if (!file_accessor_->Open(relative_paths, &files) || files.size() != n)
243*86ee64e7SAndroid Build Coastguard Worker return false;
244*86ee64e7SAndroid Build Coastguard Worker
245*86ee64e7SAndroid Build Coastguard Worker for (size_t i = 0; i < n; i++) {
246*86ee64e7SAndroid Build Coastguard Worker const base::FilePath& relative_path = relative_paths[i];
247*86ee64e7SAndroid Build Coastguard Worker DCHECK(!relative_path.empty());
248*86ee64e7SAndroid Build Coastguard Worker base::File& file = files[i];
249*86ee64e7SAndroid Build Coastguard Worker
250*86ee64e7SAndroid Build Coastguard Worker if (!file.IsValid()) {
251*86ee64e7SAndroid Build Coastguard Worker LOG(ERROR) << "Cannot open " << Redact(relative_path);
252*86ee64e7SAndroid Build Coastguard Worker progress_.errors++;
253*86ee64e7SAndroid Build Coastguard Worker
254*86ee64e7SAndroid Build Coastguard Worker if (continue_on_error_)
255*86ee64e7SAndroid Build Coastguard Worker continue;
256*86ee64e7SAndroid Build Coastguard Worker
257*86ee64e7SAndroid Build Coastguard Worker return false;
258*86ee64e7SAndroid Build Coastguard Worker }
259*86ee64e7SAndroid Build Coastguard Worker
260*86ee64e7SAndroid Build Coastguard Worker if (!AddFileEntry(relative_path, std::move(file)))
261*86ee64e7SAndroid Build Coastguard Worker return false;
262*86ee64e7SAndroid Build Coastguard Worker }
263*86ee64e7SAndroid Build Coastguard Worker }
264*86ee64e7SAndroid Build Coastguard Worker
265*86ee64e7SAndroid Build Coastguard Worker return true;
266*86ee64e7SAndroid Build Coastguard Worker }
267*86ee64e7SAndroid Build Coastguard Worker
AddDirectoryEntries(Paths paths)268*86ee64e7SAndroid Build Coastguard Worker bool ZipWriter::AddDirectoryEntries(Paths paths) {
269*86ee64e7SAndroid Build Coastguard Worker for (const base::FilePath& path : paths) {
270*86ee64e7SAndroid Build Coastguard Worker if (!AddDirectoryEntry(path))
271*86ee64e7SAndroid Build Coastguard Worker return false;
272*86ee64e7SAndroid Build Coastguard Worker }
273*86ee64e7SAndroid Build Coastguard Worker
274*86ee64e7SAndroid Build Coastguard Worker return true;
275*86ee64e7SAndroid Build Coastguard Worker }
276*86ee64e7SAndroid Build Coastguard Worker
AddDirectoryContents(const base::FilePath & path)277*86ee64e7SAndroid Build Coastguard Worker bool ZipWriter::AddDirectoryContents(const base::FilePath& path) {
278*86ee64e7SAndroid Build Coastguard Worker std::vector<base::FilePath> files, subdirs;
279*86ee64e7SAndroid Build Coastguard Worker
280*86ee64e7SAndroid Build Coastguard Worker if (!file_accessor_->List(path, &files, &subdirs)) {
281*86ee64e7SAndroid Build Coastguard Worker progress_.errors++;
282*86ee64e7SAndroid Build Coastguard Worker return continue_on_error_;
283*86ee64e7SAndroid Build Coastguard Worker }
284*86ee64e7SAndroid Build Coastguard Worker
285*86ee64e7SAndroid Build Coastguard Worker Filter(&files);
286*86ee64e7SAndroid Build Coastguard Worker Filter(&subdirs);
287*86ee64e7SAndroid Build Coastguard Worker
288*86ee64e7SAndroid Build Coastguard Worker if (!AddFileEntries(files))
289*86ee64e7SAndroid Build Coastguard Worker return false;
290*86ee64e7SAndroid Build Coastguard Worker
291*86ee64e7SAndroid Build Coastguard Worker return AddDirectoryEntries(subdirs);
292*86ee64e7SAndroid Build Coastguard Worker }
293*86ee64e7SAndroid Build Coastguard Worker
Filter(std::vector<base::FilePath> * const paths)294*86ee64e7SAndroid Build Coastguard Worker void ZipWriter::Filter(std::vector<base::FilePath>* const paths) {
295*86ee64e7SAndroid Build Coastguard Worker DCHECK(paths);
296*86ee64e7SAndroid Build Coastguard Worker
297*86ee64e7SAndroid Build Coastguard Worker if (!filter_callback_)
298*86ee64e7SAndroid Build Coastguard Worker return;
299*86ee64e7SAndroid Build Coastguard Worker
300*86ee64e7SAndroid Build Coastguard Worker const auto end = std::remove_if(paths->begin(), paths->end(),
301*86ee64e7SAndroid Build Coastguard Worker [this](const base::FilePath& path) {
302*86ee64e7SAndroid Build Coastguard Worker return !filter_callback_.Run(path);
303*86ee64e7SAndroid Build Coastguard Worker });
304*86ee64e7SAndroid Build Coastguard Worker paths->erase(end, paths->end());
305*86ee64e7SAndroid Build Coastguard Worker }
306*86ee64e7SAndroid Build Coastguard Worker
307*86ee64e7SAndroid Build Coastguard Worker } // namespace internal
308*86ee64e7SAndroid Build Coastguard Worker } // namespace zip
309