1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/files/file_util.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include "base/task/sequenced_task_runner.h"
8*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
11*6777b538SAndroid Build Coastguard Worker #include <io.h>
12*6777b538SAndroid Build Coastguard Worker #endif
13*6777b538SAndroid Build Coastguard Worker #include <stdio.h>
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker #include <fstream>
16*6777b538SAndroid Build Coastguard Worker #include <limits>
17*6777b538SAndroid Build Coastguard Worker #include <memory>
18*6777b538SAndroid Build Coastguard Worker #include <utility>
19*6777b538SAndroid Build Coastguard Worker #include <vector>
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker #include "base/bit_cast.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/files/file_enumerator.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/functional/function_ref.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/posix/eintr_wrapper.h"
29*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
30*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
31*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
32*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
33*6777b538SAndroid Build Coastguard Worker #include "base/task/bind_post_task.h"
34*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call.h"
35*6777b538SAndroid Build Coastguard Worker
36*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
37*6777b538SAndroid Build Coastguard Worker #include <windows.h>
38*6777b538SAndroid Build Coastguard Worker #endif
39*6777b538SAndroid Build Coastguard Worker
40*6777b538SAndroid Build Coastguard Worker namespace base {
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker namespace {
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_WIN)
45*6777b538SAndroid Build Coastguard Worker
RunAndReply(OnceCallback<bool ()> action_callback,OnceCallback<void (bool)> reply_callback)46*6777b538SAndroid Build Coastguard Worker void RunAndReply(OnceCallback<bool()> action_callback,
47*6777b538SAndroid Build Coastguard Worker OnceCallback<void(bool)> reply_callback) {
48*6777b538SAndroid Build Coastguard Worker bool result = std::move(action_callback).Run();
49*6777b538SAndroid Build Coastguard Worker if (!reply_callback.is_null())
50*6777b538SAndroid Build Coastguard Worker std::move(reply_callback).Run(result);
51*6777b538SAndroid Build Coastguard Worker }
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker #endif // !BUILDFLAG(IS_WIN)
54*6777b538SAndroid Build Coastguard Worker
ReadStreamToSpanWithMaxSize(FILE * stream,size_t max_size,FunctionRef<span<uint8_t> (size_t)> resize_span)55*6777b538SAndroid Build Coastguard Worker bool ReadStreamToSpanWithMaxSize(
56*6777b538SAndroid Build Coastguard Worker FILE* stream,
57*6777b538SAndroid Build Coastguard Worker size_t max_size,
58*6777b538SAndroid Build Coastguard Worker FunctionRef<span<uint8_t>(size_t)> resize_span) {
59*6777b538SAndroid Build Coastguard Worker if (!stream) {
60*6777b538SAndroid Build Coastguard Worker return false;
61*6777b538SAndroid Build Coastguard Worker }
62*6777b538SAndroid Build Coastguard Worker
63*6777b538SAndroid Build Coastguard Worker // Seeking to the beginning is best-effort -- it is expected to fail for
64*6777b538SAndroid Build Coastguard Worker // certain non-file stream (e.g., pipes).
65*6777b538SAndroid Build Coastguard Worker HANDLE_EINTR(fseek(stream, 0, SEEK_SET));
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Worker // Many files have incorrect size (proc files etc). Hence, the file is read
68*6777b538SAndroid Build Coastguard Worker // sequentially as opposed to a one-shot read, using file size as a hint for
69*6777b538SAndroid Build Coastguard Worker // chunk size if available.
70*6777b538SAndroid Build Coastguard Worker constexpr size_t kDefaultChunkSize = 1 << 16;
71*6777b538SAndroid Build Coastguard Worker size_t chunk_size = kDefaultChunkSize - 1;
72*6777b538SAndroid Build Coastguard Worker ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
73*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
74*6777b538SAndroid Build Coastguard Worker BY_HANDLE_FILE_INFORMATION file_info = {};
75*6777b538SAndroid Build Coastguard Worker if (::GetFileInformationByHandle(
76*6777b538SAndroid Build Coastguard Worker reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(stream))),
77*6777b538SAndroid Build Coastguard Worker &file_info)) {
78*6777b538SAndroid Build Coastguard Worker LARGE_INTEGER size;
79*6777b538SAndroid Build Coastguard Worker size.HighPart = static_cast<LONG>(file_info.nFileSizeHigh);
80*6777b538SAndroid Build Coastguard Worker size.LowPart = file_info.nFileSizeLow;
81*6777b538SAndroid Build Coastguard Worker if (size.QuadPart > 0)
82*6777b538SAndroid Build Coastguard Worker chunk_size = static_cast<size_t>(size.QuadPart);
83*6777b538SAndroid Build Coastguard Worker }
84*6777b538SAndroid Build Coastguard Worker #else // BUILDFLAG(IS_WIN)
85*6777b538SAndroid Build Coastguard Worker // In cases where the reported file size is 0, use a smaller chunk size to
86*6777b538SAndroid Build Coastguard Worker // minimize memory allocated and cost of string::resize() in case the read
87*6777b538SAndroid Build Coastguard Worker // size is small (i.e. proc files). If the file is larger than this, the read
88*6777b538SAndroid Build Coastguard Worker // loop will reset |chunk_size| to kDefaultChunkSize.
89*6777b538SAndroid Build Coastguard Worker constexpr size_t kSmallChunkSize = 4096;
90*6777b538SAndroid Build Coastguard Worker chunk_size = kSmallChunkSize - 1;
91*6777b538SAndroid Build Coastguard Worker stat_wrapper_t file_info = {};
92*6777b538SAndroid Build Coastguard Worker if (!File::Fstat(fileno(stream), &file_info) && file_info.st_size > 0)
93*6777b538SAndroid Build Coastguard Worker chunk_size = static_cast<size_t>(file_info.st_size);
94*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_WIN)
95*6777b538SAndroid Build Coastguard Worker
96*6777b538SAndroid Build Coastguard Worker // We need to attempt to read at EOF for feof flag to be set so here we use
97*6777b538SAndroid Build Coastguard Worker // |chunk_size| + 1.
98*6777b538SAndroid Build Coastguard Worker chunk_size = std::min(chunk_size, max_size) + 1;
99*6777b538SAndroid Build Coastguard Worker size_t bytes_read_this_pass;
100*6777b538SAndroid Build Coastguard Worker size_t bytes_read_so_far = 0;
101*6777b538SAndroid Build Coastguard Worker bool read_status = true;
102*6777b538SAndroid Build Coastguard Worker span<uint8_t> bytes_span = resize_span(chunk_size);
103*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(bytes_span.size(), chunk_size);
104*6777b538SAndroid Build Coastguard Worker
105*6777b538SAndroid Build Coastguard Worker while ((bytes_read_this_pass = fread(bytes_span.data() + bytes_read_so_far, 1,
106*6777b538SAndroid Build Coastguard Worker chunk_size, stream)) > 0) {
107*6777b538SAndroid Build Coastguard Worker if ((max_size - bytes_read_so_far) < bytes_read_this_pass) {
108*6777b538SAndroid Build Coastguard Worker // Read more than max_size bytes, bail out.
109*6777b538SAndroid Build Coastguard Worker bytes_read_so_far = max_size;
110*6777b538SAndroid Build Coastguard Worker read_status = false;
111*6777b538SAndroid Build Coastguard Worker break;
112*6777b538SAndroid Build Coastguard Worker }
113*6777b538SAndroid Build Coastguard Worker // In case EOF was not reached, iterate again but revert to the default
114*6777b538SAndroid Build Coastguard Worker // chunk size.
115*6777b538SAndroid Build Coastguard Worker if (bytes_read_so_far == 0)
116*6777b538SAndroid Build Coastguard Worker chunk_size = kDefaultChunkSize;
117*6777b538SAndroid Build Coastguard Worker
118*6777b538SAndroid Build Coastguard Worker bytes_read_so_far += bytes_read_this_pass;
119*6777b538SAndroid Build Coastguard Worker // Last fread syscall (after EOF) can be avoided via feof, which is just a
120*6777b538SAndroid Build Coastguard Worker // flag check.
121*6777b538SAndroid Build Coastguard Worker if (feof(stream))
122*6777b538SAndroid Build Coastguard Worker break;
123*6777b538SAndroid Build Coastguard Worker bytes_span = resize_span(bytes_read_so_far + chunk_size);
124*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(bytes_span.size(), bytes_read_so_far + chunk_size);
125*6777b538SAndroid Build Coastguard Worker }
126*6777b538SAndroid Build Coastguard Worker read_status = read_status && !ferror(stream);
127*6777b538SAndroid Build Coastguard Worker
128*6777b538SAndroid Build Coastguard Worker // Trim the container down to the number of bytes that were actually read.
129*6777b538SAndroid Build Coastguard Worker bytes_span = resize_span(bytes_read_so_far);
130*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(bytes_span.size(), bytes_read_so_far);
131*6777b538SAndroid Build Coastguard Worker
132*6777b538SAndroid Build Coastguard Worker return read_status;
133*6777b538SAndroid Build Coastguard Worker }
134*6777b538SAndroid Build Coastguard Worker
135*6777b538SAndroid Build Coastguard Worker } // namespace
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_WIN)
138*6777b538SAndroid Build Coastguard Worker
GetDeleteFileCallback(const FilePath & path,OnceCallback<void (bool)> reply_callback)139*6777b538SAndroid Build Coastguard Worker OnceClosure GetDeleteFileCallback(const FilePath& path,
140*6777b538SAndroid Build Coastguard Worker OnceCallback<void(bool)> reply_callback) {
141*6777b538SAndroid Build Coastguard Worker return BindOnce(&RunAndReply, BindOnce(&DeleteFile, path),
142*6777b538SAndroid Build Coastguard Worker reply_callback.is_null()
143*6777b538SAndroid Build Coastguard Worker ? std::move(reply_callback)
144*6777b538SAndroid Build Coastguard Worker : BindPostTask(SequencedTaskRunner::GetCurrentDefault(),
145*6777b538SAndroid Build Coastguard Worker std::move(reply_callback)));
146*6777b538SAndroid Build Coastguard Worker }
147*6777b538SAndroid Build Coastguard Worker
GetDeletePathRecursivelyCallback(const FilePath & path,OnceCallback<void (bool)> reply_callback)148*6777b538SAndroid Build Coastguard Worker OnceClosure GetDeletePathRecursivelyCallback(
149*6777b538SAndroid Build Coastguard Worker const FilePath& path,
150*6777b538SAndroid Build Coastguard Worker OnceCallback<void(bool)> reply_callback) {
151*6777b538SAndroid Build Coastguard Worker return BindOnce(&RunAndReply, BindOnce(&DeletePathRecursively, path),
152*6777b538SAndroid Build Coastguard Worker reply_callback.is_null()
153*6777b538SAndroid Build Coastguard Worker ? std::move(reply_callback)
154*6777b538SAndroid Build Coastguard Worker : BindPostTask(SequencedTaskRunner::GetCurrentDefault(),
155*6777b538SAndroid Build Coastguard Worker std::move(reply_callback)));
156*6777b538SAndroid Build Coastguard Worker }
157*6777b538SAndroid Build Coastguard Worker
158*6777b538SAndroid Build Coastguard Worker #endif // !BUILDFLAG(IS_WIN)
159*6777b538SAndroid Build Coastguard Worker
ComputeDirectorySize(const FilePath & root_path)160*6777b538SAndroid Build Coastguard Worker int64_t ComputeDirectorySize(const FilePath& root_path) {
161*6777b538SAndroid Build Coastguard Worker int64_t running_size = 0;
162*6777b538SAndroid Build Coastguard Worker FileEnumerator file_iter(root_path, true, FileEnumerator::FILES);
163*6777b538SAndroid Build Coastguard Worker while (!file_iter.Next().empty())
164*6777b538SAndroid Build Coastguard Worker running_size += file_iter.GetInfo().GetSize();
165*6777b538SAndroid Build Coastguard Worker return running_size;
166*6777b538SAndroid Build Coastguard Worker }
167*6777b538SAndroid Build Coastguard Worker
Move(const FilePath & from_path,const FilePath & to_path)168*6777b538SAndroid Build Coastguard Worker bool Move(const FilePath& from_path, const FilePath& to_path) {
169*6777b538SAndroid Build Coastguard Worker if (from_path.ReferencesParent() || to_path.ReferencesParent())
170*6777b538SAndroid Build Coastguard Worker return false;
171*6777b538SAndroid Build Coastguard Worker return internal::MoveUnsafe(from_path, to_path);
172*6777b538SAndroid Build Coastguard Worker }
173*6777b538SAndroid Build Coastguard Worker
CopyFileContents(File & infile,File & outfile)174*6777b538SAndroid Build Coastguard Worker bool CopyFileContents(File& infile, File& outfile) {
175*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
176*6777b538SAndroid Build Coastguard Worker bool retry_slow = false;
177*6777b538SAndroid Build Coastguard Worker bool res =
178*6777b538SAndroid Build Coastguard Worker internal::CopyFileContentsWithSendfile(infile, outfile, retry_slow);
179*6777b538SAndroid Build Coastguard Worker if (res || !retry_slow) {
180*6777b538SAndroid Build Coastguard Worker return res;
181*6777b538SAndroid Build Coastguard Worker }
182*6777b538SAndroid Build Coastguard Worker // Any failures which allow retrying using read/write will not have modified
183*6777b538SAndroid Build Coastguard Worker // either file offset or size.
184*6777b538SAndroid Build Coastguard Worker #endif
185*6777b538SAndroid Build Coastguard Worker
186*6777b538SAndroid Build Coastguard Worker static constexpr size_t kBufferSize = 32768;
187*6777b538SAndroid Build Coastguard Worker std::vector<char> buffer(kBufferSize);
188*6777b538SAndroid Build Coastguard Worker
189*6777b538SAndroid Build Coastguard Worker for (;;) {
190*6777b538SAndroid Build Coastguard Worker int bytes_read =
191*6777b538SAndroid Build Coastguard Worker infile.ReadAtCurrentPos(buffer.data(), static_cast<int>(buffer.size()));
192*6777b538SAndroid Build Coastguard Worker if (bytes_read < 0) {
193*6777b538SAndroid Build Coastguard Worker return false;
194*6777b538SAndroid Build Coastguard Worker }
195*6777b538SAndroid Build Coastguard Worker if (bytes_read == 0) {
196*6777b538SAndroid Build Coastguard Worker return true;
197*6777b538SAndroid Build Coastguard Worker }
198*6777b538SAndroid Build Coastguard Worker // Allow for partial writes
199*6777b538SAndroid Build Coastguard Worker int bytes_written_per_read = 0;
200*6777b538SAndroid Build Coastguard Worker do {
201*6777b538SAndroid Build Coastguard Worker int bytes_written_partial = outfile.WriteAtCurrentPos(
202*6777b538SAndroid Build Coastguard Worker &buffer[static_cast<size_t>(bytes_written_per_read)],
203*6777b538SAndroid Build Coastguard Worker bytes_read - bytes_written_per_read);
204*6777b538SAndroid Build Coastguard Worker if (bytes_written_partial < 0) {
205*6777b538SAndroid Build Coastguard Worker return false;
206*6777b538SAndroid Build Coastguard Worker }
207*6777b538SAndroid Build Coastguard Worker
208*6777b538SAndroid Build Coastguard Worker bytes_written_per_read += bytes_written_partial;
209*6777b538SAndroid Build Coastguard Worker } while (bytes_written_per_read < bytes_read);
210*6777b538SAndroid Build Coastguard Worker }
211*6777b538SAndroid Build Coastguard Worker
212*6777b538SAndroid Build Coastguard Worker NOTREACHED();
213*6777b538SAndroid Build Coastguard Worker return false;
214*6777b538SAndroid Build Coastguard Worker }
215*6777b538SAndroid Build Coastguard Worker
ContentsEqual(const FilePath & filename1,const FilePath & filename2)216*6777b538SAndroid Build Coastguard Worker bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
217*6777b538SAndroid Build Coastguard Worker // We open the file in binary format even if they are text files because
218*6777b538SAndroid Build Coastguard Worker // we are just comparing that bytes are exactly same in both files and not
219*6777b538SAndroid Build Coastguard Worker // doing anything smart with text formatting.
220*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
221*6777b538SAndroid Build Coastguard Worker std::ifstream file1(filename1.value().c_str(),
222*6777b538SAndroid Build Coastguard Worker std::ios::in | std::ios::binary);
223*6777b538SAndroid Build Coastguard Worker std::ifstream file2(filename2.value().c_str(),
224*6777b538SAndroid Build Coastguard Worker std::ios::in | std::ios::binary);
225*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
226*6777b538SAndroid Build Coastguard Worker std::ifstream file1(filename1.value(), std::ios::in | std::ios::binary);
227*6777b538SAndroid Build Coastguard Worker std::ifstream file2(filename2.value(), std::ios::in | std::ios::binary);
228*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_WIN)
229*6777b538SAndroid Build Coastguard Worker
230*6777b538SAndroid Build Coastguard Worker // Even if both files aren't openable (and thus, in some sense, "equal"),
231*6777b538SAndroid Build Coastguard Worker // any unusable file yields a result of "false".
232*6777b538SAndroid Build Coastguard Worker if (!file1.is_open() || !file2.is_open())
233*6777b538SAndroid Build Coastguard Worker return false;
234*6777b538SAndroid Build Coastguard Worker
235*6777b538SAndroid Build Coastguard Worker const int BUFFER_SIZE = 2056;
236*6777b538SAndroid Build Coastguard Worker char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
237*6777b538SAndroid Build Coastguard Worker do {
238*6777b538SAndroid Build Coastguard Worker file1.read(buffer1, BUFFER_SIZE);
239*6777b538SAndroid Build Coastguard Worker file2.read(buffer2, BUFFER_SIZE);
240*6777b538SAndroid Build Coastguard Worker
241*6777b538SAndroid Build Coastguard Worker if ((file1.eof() != file2.eof()) ||
242*6777b538SAndroid Build Coastguard Worker (file1.gcount() != file2.gcount()) ||
243*6777b538SAndroid Build Coastguard Worker (memcmp(buffer1, buffer2, static_cast<size_t>(file1.gcount())))) {
244*6777b538SAndroid Build Coastguard Worker file1.close();
245*6777b538SAndroid Build Coastguard Worker file2.close();
246*6777b538SAndroid Build Coastguard Worker return false;
247*6777b538SAndroid Build Coastguard Worker }
248*6777b538SAndroid Build Coastguard Worker } while (!file1.eof() || !file2.eof());
249*6777b538SAndroid Build Coastguard Worker
250*6777b538SAndroid Build Coastguard Worker file1.close();
251*6777b538SAndroid Build Coastguard Worker file2.close();
252*6777b538SAndroid Build Coastguard Worker return true;
253*6777b538SAndroid Build Coastguard Worker }
254*6777b538SAndroid Build Coastguard Worker
TextContentsEqual(const FilePath & filename1,const FilePath & filename2)255*6777b538SAndroid Build Coastguard Worker bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2) {
256*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
257*6777b538SAndroid Build Coastguard Worker std::ifstream file1(filename1.value().c_str(), std::ios::in);
258*6777b538SAndroid Build Coastguard Worker std::ifstream file2(filename2.value().c_str(), std::ios::in);
259*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
260*6777b538SAndroid Build Coastguard Worker std::ifstream file1(filename1.value(), std::ios::in);
261*6777b538SAndroid Build Coastguard Worker std::ifstream file2(filename2.value(), std::ios::in);
262*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_WIN)
263*6777b538SAndroid Build Coastguard Worker
264*6777b538SAndroid Build Coastguard Worker // Even if both files aren't openable (and thus, in some sense, "equal"),
265*6777b538SAndroid Build Coastguard Worker // any unusable file yields a result of "false".
266*6777b538SAndroid Build Coastguard Worker if (!file1.is_open() || !file2.is_open())
267*6777b538SAndroid Build Coastguard Worker return false;
268*6777b538SAndroid Build Coastguard Worker
269*6777b538SAndroid Build Coastguard Worker do {
270*6777b538SAndroid Build Coastguard Worker std::string line1, line2;
271*6777b538SAndroid Build Coastguard Worker getline(file1, line1);
272*6777b538SAndroid Build Coastguard Worker getline(file2, line2);
273*6777b538SAndroid Build Coastguard Worker
274*6777b538SAndroid Build Coastguard Worker // Check for mismatched EOF states, or any error state.
275*6777b538SAndroid Build Coastguard Worker if ((file1.eof() != file2.eof()) ||
276*6777b538SAndroid Build Coastguard Worker file1.bad() || file2.bad()) {
277*6777b538SAndroid Build Coastguard Worker return false;
278*6777b538SAndroid Build Coastguard Worker }
279*6777b538SAndroid Build Coastguard Worker
280*6777b538SAndroid Build Coastguard Worker // Trim all '\r' and '\n' characters from the end of the line.
281*6777b538SAndroid Build Coastguard Worker std::string::size_type end1 = line1.find_last_not_of("\r\n");
282*6777b538SAndroid Build Coastguard Worker if (end1 == std::string::npos)
283*6777b538SAndroid Build Coastguard Worker line1.clear();
284*6777b538SAndroid Build Coastguard Worker else if (end1 + 1 < line1.length())
285*6777b538SAndroid Build Coastguard Worker line1.erase(end1 + 1);
286*6777b538SAndroid Build Coastguard Worker
287*6777b538SAndroid Build Coastguard Worker std::string::size_type end2 = line2.find_last_not_of("\r\n");
288*6777b538SAndroid Build Coastguard Worker if (end2 == std::string::npos)
289*6777b538SAndroid Build Coastguard Worker line2.clear();
290*6777b538SAndroid Build Coastguard Worker else if (end2 + 1 < line2.length())
291*6777b538SAndroid Build Coastguard Worker line2.erase(end2 + 1);
292*6777b538SAndroid Build Coastguard Worker
293*6777b538SAndroid Build Coastguard Worker if (line1 != line2)
294*6777b538SAndroid Build Coastguard Worker return false;
295*6777b538SAndroid Build Coastguard Worker } while (!file1.eof() || !file2.eof());
296*6777b538SAndroid Build Coastguard Worker
297*6777b538SAndroid Build Coastguard Worker return true;
298*6777b538SAndroid Build Coastguard Worker }
299*6777b538SAndroid Build Coastguard Worker
ReadStreamToString(FILE * stream,std::string * contents)300*6777b538SAndroid Build Coastguard Worker bool ReadStreamToString(FILE* stream, std::string* contents) {
301*6777b538SAndroid Build Coastguard Worker return ReadStreamToStringWithMaxSize(
302*6777b538SAndroid Build Coastguard Worker stream, std::numeric_limits<size_t>::max(), contents);
303*6777b538SAndroid Build Coastguard Worker }
304*6777b538SAndroid Build Coastguard Worker
ReadStreamToStringWithMaxSize(FILE * stream,size_t max_size,std::string * contents)305*6777b538SAndroid Build Coastguard Worker bool ReadStreamToStringWithMaxSize(FILE* stream,
306*6777b538SAndroid Build Coastguard Worker size_t max_size,
307*6777b538SAndroid Build Coastguard Worker std::string* contents) {
308*6777b538SAndroid Build Coastguard Worker if (contents) {
309*6777b538SAndroid Build Coastguard Worker contents->clear();
310*6777b538SAndroid Build Coastguard Worker }
311*6777b538SAndroid Build Coastguard Worker
312*6777b538SAndroid Build Coastguard Worker std::string content_string;
313*6777b538SAndroid Build Coastguard Worker bool read_successs = ReadStreamToSpanWithMaxSize(
314*6777b538SAndroid Build Coastguard Worker stream, max_size, [&content_string](size_t size) {
315*6777b538SAndroid Build Coastguard Worker content_string.resize(size);
316*6777b538SAndroid Build Coastguard Worker return as_writable_bytes(make_span(content_string));
317*6777b538SAndroid Build Coastguard Worker });
318*6777b538SAndroid Build Coastguard Worker
319*6777b538SAndroid Build Coastguard Worker if (contents) {
320*6777b538SAndroid Build Coastguard Worker contents->swap(content_string);
321*6777b538SAndroid Build Coastguard Worker }
322*6777b538SAndroid Build Coastguard Worker return read_successs;
323*6777b538SAndroid Build Coastguard Worker }
324*6777b538SAndroid Build Coastguard Worker
ReadFileToBytes(const FilePath & path)325*6777b538SAndroid Build Coastguard Worker std::optional<std::vector<uint8_t>> ReadFileToBytes(const FilePath& path) {
326*6777b538SAndroid Build Coastguard Worker if (path.ReferencesParent()) {
327*6777b538SAndroid Build Coastguard Worker return std::nullopt;
328*6777b538SAndroid Build Coastguard Worker }
329*6777b538SAndroid Build Coastguard Worker
330*6777b538SAndroid Build Coastguard Worker ScopedFILE file_stream(OpenFile(path, "rb"));
331*6777b538SAndroid Build Coastguard Worker if (!file_stream) {
332*6777b538SAndroid Build Coastguard Worker return std::nullopt;
333*6777b538SAndroid Build Coastguard Worker }
334*6777b538SAndroid Build Coastguard Worker
335*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> bytes;
336*6777b538SAndroid Build Coastguard Worker if (!ReadStreamToSpanWithMaxSize(file_stream.get(),
337*6777b538SAndroid Build Coastguard Worker std::numeric_limits<size_t>::max(),
338*6777b538SAndroid Build Coastguard Worker [&bytes](size_t size) {
339*6777b538SAndroid Build Coastguard Worker bytes.resize(size);
340*6777b538SAndroid Build Coastguard Worker return make_span(bytes);
341*6777b538SAndroid Build Coastguard Worker })) {
342*6777b538SAndroid Build Coastguard Worker return std::nullopt;
343*6777b538SAndroid Build Coastguard Worker }
344*6777b538SAndroid Build Coastguard Worker return bytes;
345*6777b538SAndroid Build Coastguard Worker }
346*6777b538SAndroid Build Coastguard Worker
ReadFileToString(const FilePath & path,std::string * contents)347*6777b538SAndroid Build Coastguard Worker bool ReadFileToString(const FilePath& path, std::string* contents) {
348*6777b538SAndroid Build Coastguard Worker return ReadFileToStringWithMaxSize(path, contents,
349*6777b538SAndroid Build Coastguard Worker std::numeric_limits<size_t>::max());
350*6777b538SAndroid Build Coastguard Worker }
351*6777b538SAndroid Build Coastguard Worker
ReadFileToStringWithMaxSize(const FilePath & path,std::string * contents,size_t max_size)352*6777b538SAndroid Build Coastguard Worker bool ReadFileToStringWithMaxSize(const FilePath& path,
353*6777b538SAndroid Build Coastguard Worker std::string* contents,
354*6777b538SAndroid Build Coastguard Worker size_t max_size) {
355*6777b538SAndroid Build Coastguard Worker if (contents)
356*6777b538SAndroid Build Coastguard Worker contents->clear();
357*6777b538SAndroid Build Coastguard Worker if (path.ReferencesParent())
358*6777b538SAndroid Build Coastguard Worker return false;
359*6777b538SAndroid Build Coastguard Worker ScopedFILE file_stream(OpenFile(path, "rb"));
360*6777b538SAndroid Build Coastguard Worker if (!file_stream)
361*6777b538SAndroid Build Coastguard Worker return false;
362*6777b538SAndroid Build Coastguard Worker return ReadStreamToStringWithMaxSize(file_stream.get(), max_size, contents);
363*6777b538SAndroid Build Coastguard Worker }
364*6777b538SAndroid Build Coastguard Worker
IsDirectoryEmpty(const FilePath & dir_path)365*6777b538SAndroid Build Coastguard Worker bool IsDirectoryEmpty(const FilePath& dir_path) {
366*6777b538SAndroid Build Coastguard Worker FileEnumerator files(dir_path, false,
367*6777b538SAndroid Build Coastguard Worker FileEnumerator::FILES | FileEnumerator::DIRECTORIES);
368*6777b538SAndroid Build Coastguard Worker if (files.Next().empty())
369*6777b538SAndroid Build Coastguard Worker return true;
370*6777b538SAndroid Build Coastguard Worker return false;
371*6777b538SAndroid Build Coastguard Worker }
372*6777b538SAndroid Build Coastguard Worker
CreateTemporaryFile(FilePath * path)373*6777b538SAndroid Build Coastguard Worker bool CreateTemporaryFile(FilePath* path) {
374*6777b538SAndroid Build Coastguard Worker FilePath temp_dir;
375*6777b538SAndroid Build Coastguard Worker return GetTempDir(&temp_dir) && CreateTemporaryFileInDir(temp_dir, path);
376*6777b538SAndroid Build Coastguard Worker }
377*6777b538SAndroid Build Coastguard Worker
CreateAndOpenTemporaryStream(FilePath * path)378*6777b538SAndroid Build Coastguard Worker ScopedFILE CreateAndOpenTemporaryStream(FilePath* path) {
379*6777b538SAndroid Build Coastguard Worker FilePath directory;
380*6777b538SAndroid Build Coastguard Worker if (!GetTempDir(&directory))
381*6777b538SAndroid Build Coastguard Worker return nullptr;
382*6777b538SAndroid Build Coastguard Worker
383*6777b538SAndroid Build Coastguard Worker return CreateAndOpenTemporaryStreamInDir(directory, path);
384*6777b538SAndroid Build Coastguard Worker }
385*6777b538SAndroid Build Coastguard Worker
CreateDirectory(const FilePath & full_path)386*6777b538SAndroid Build Coastguard Worker bool CreateDirectory(const FilePath& full_path) {
387*6777b538SAndroid Build Coastguard Worker return CreateDirectoryAndGetError(full_path, nullptr);
388*6777b538SAndroid Build Coastguard Worker }
389*6777b538SAndroid Build Coastguard Worker
GetFileSize(const FilePath & file_path,int64_t * file_size)390*6777b538SAndroid Build Coastguard Worker bool GetFileSize(const FilePath& file_path, int64_t* file_size) {
391*6777b538SAndroid Build Coastguard Worker File::Info info;
392*6777b538SAndroid Build Coastguard Worker if (!GetFileInfo(file_path, &info))
393*6777b538SAndroid Build Coastguard Worker return false;
394*6777b538SAndroid Build Coastguard Worker *file_size = info.size;
395*6777b538SAndroid Build Coastguard Worker return true;
396*6777b538SAndroid Build Coastguard Worker }
397*6777b538SAndroid Build Coastguard Worker
TouchFile(const FilePath & path,const Time & last_accessed,const Time & last_modified)398*6777b538SAndroid Build Coastguard Worker bool TouchFile(const FilePath& path,
399*6777b538SAndroid Build Coastguard Worker const Time& last_accessed,
400*6777b538SAndroid Build Coastguard Worker const Time& last_modified) {
401*6777b538SAndroid Build Coastguard Worker uint32_t flags = File::FLAG_OPEN | File::FLAG_WRITE_ATTRIBUTES;
402*6777b538SAndroid Build Coastguard Worker
403*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
404*6777b538SAndroid Build Coastguard Worker // On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory.
405*6777b538SAndroid Build Coastguard Worker if (DirectoryExists(path))
406*6777b538SAndroid Build Coastguard Worker flags |= File::FLAG_WIN_BACKUP_SEMANTICS;
407*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_FUCHSIA)
408*6777b538SAndroid Build Coastguard Worker // On Fuchsia, we need O_RDONLY for directories, or O_WRONLY for files.
409*6777b538SAndroid Build Coastguard Worker // TODO(https://crbug.com/947802): Find a cleaner workaround for this.
410*6777b538SAndroid Build Coastguard Worker flags |= (DirectoryExists(path) ? File::FLAG_READ : File::FLAG_WRITE);
411*6777b538SAndroid Build Coastguard Worker #endif
412*6777b538SAndroid Build Coastguard Worker
413*6777b538SAndroid Build Coastguard Worker File file(path, flags);
414*6777b538SAndroid Build Coastguard Worker if (!file.IsValid())
415*6777b538SAndroid Build Coastguard Worker return false;
416*6777b538SAndroid Build Coastguard Worker
417*6777b538SAndroid Build Coastguard Worker return file.SetTimes(last_accessed, last_modified);
418*6777b538SAndroid Build Coastguard Worker }
419*6777b538SAndroid Build Coastguard Worker
CloseFile(FILE * file)420*6777b538SAndroid Build Coastguard Worker bool CloseFile(FILE* file) {
421*6777b538SAndroid Build Coastguard Worker if (file == nullptr)
422*6777b538SAndroid Build Coastguard Worker return true;
423*6777b538SAndroid Build Coastguard Worker return fclose(file) == 0;
424*6777b538SAndroid Build Coastguard Worker }
425*6777b538SAndroid Build Coastguard Worker
TruncateFile(FILE * file)426*6777b538SAndroid Build Coastguard Worker bool TruncateFile(FILE* file) {
427*6777b538SAndroid Build Coastguard Worker if (file == nullptr)
428*6777b538SAndroid Build Coastguard Worker return false;
429*6777b538SAndroid Build Coastguard Worker long current_offset = ftell(file);
430*6777b538SAndroid Build Coastguard Worker if (current_offset == -1)
431*6777b538SAndroid Build Coastguard Worker return false;
432*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
433*6777b538SAndroid Build Coastguard Worker int fd = _fileno(file);
434*6777b538SAndroid Build Coastguard Worker if (_chsize(fd, current_offset) != 0)
435*6777b538SAndroid Build Coastguard Worker return false;
436*6777b538SAndroid Build Coastguard Worker #else
437*6777b538SAndroid Build Coastguard Worker int fd = fileno(file);
438*6777b538SAndroid Build Coastguard Worker if (ftruncate(fd, current_offset) != 0)
439*6777b538SAndroid Build Coastguard Worker return false;
440*6777b538SAndroid Build Coastguard Worker #endif
441*6777b538SAndroid Build Coastguard Worker return true;
442*6777b538SAndroid Build Coastguard Worker }
443*6777b538SAndroid Build Coastguard Worker
ReadFile(const FilePath & filename,span<uint8_t> buffer)444*6777b538SAndroid Build Coastguard Worker std::optional<uint64_t> ReadFile(const FilePath& filename,
445*6777b538SAndroid Build Coastguard Worker span<uint8_t> buffer) {
446*6777b538SAndroid Build Coastguard Worker return ReadFile(filename, base::as_writable_chars(buffer));
447*6777b538SAndroid Build Coastguard Worker }
448*6777b538SAndroid Build Coastguard Worker
ReadFile(const FilePath & filename,char * data,int max_size)449*6777b538SAndroid Build Coastguard Worker int ReadFile(const FilePath& filename, char* data, int max_size) {
450*6777b538SAndroid Build Coastguard Worker if (max_size < 0) {
451*6777b538SAndroid Build Coastguard Worker return -1;
452*6777b538SAndroid Build Coastguard Worker }
453*6777b538SAndroid Build Coastguard Worker std::optional<uint64_t> result =
454*6777b538SAndroid Build Coastguard Worker ReadFile(filename, make_span(data, static_cast<uint32_t>(max_size)));
455*6777b538SAndroid Build Coastguard Worker if (!result) {
456*6777b538SAndroid Build Coastguard Worker return -1;
457*6777b538SAndroid Build Coastguard Worker }
458*6777b538SAndroid Build Coastguard Worker return checked_cast<int>(result.value());
459*6777b538SAndroid Build Coastguard Worker }
460*6777b538SAndroid Build Coastguard Worker
WriteFile(const FilePath & filename,span<const uint8_t> data)461*6777b538SAndroid Build Coastguard Worker bool WriteFile(const FilePath& filename, span<const uint8_t> data) {
462*6777b538SAndroid Build Coastguard Worker int size = checked_cast<int>(data.size());
463*6777b538SAndroid Build Coastguard Worker return WriteFile(filename, reinterpret_cast<const char*>(data.data()),
464*6777b538SAndroid Build Coastguard Worker size) == size;
465*6777b538SAndroid Build Coastguard Worker }
466*6777b538SAndroid Build Coastguard Worker
WriteFile(const FilePath & filename,StringPiece data)467*6777b538SAndroid Build Coastguard Worker bool WriteFile(const FilePath& filename, StringPiece data) {
468*6777b538SAndroid Build Coastguard Worker int size = checked_cast<int>(data.size());
469*6777b538SAndroid Build Coastguard Worker return WriteFile(filename, data.data(), size) == size;
470*6777b538SAndroid Build Coastguard Worker }
471*6777b538SAndroid Build Coastguard Worker
GetUniquePathNumber(const FilePath & path)472*6777b538SAndroid Build Coastguard Worker int GetUniquePathNumber(const FilePath& path) {
473*6777b538SAndroid Build Coastguard Worker DCHECK(!path.empty());
474*6777b538SAndroid Build Coastguard Worker if (!PathExists(path))
475*6777b538SAndroid Build Coastguard Worker return 0;
476*6777b538SAndroid Build Coastguard Worker
477*6777b538SAndroid Build Coastguard Worker std::string number;
478*6777b538SAndroid Build Coastguard Worker for (int count = 1; count <= kMaxUniqueFiles; ++count) {
479*6777b538SAndroid Build Coastguard Worker StringAppendF(&number, " (%d)", count);
480*6777b538SAndroid Build Coastguard Worker if (!PathExists(path.InsertBeforeExtensionASCII(number)))
481*6777b538SAndroid Build Coastguard Worker return count;
482*6777b538SAndroid Build Coastguard Worker number.clear();
483*6777b538SAndroid Build Coastguard Worker }
484*6777b538SAndroid Build Coastguard Worker
485*6777b538SAndroid Build Coastguard Worker return -1;
486*6777b538SAndroid Build Coastguard Worker }
487*6777b538SAndroid Build Coastguard Worker
GetUniquePath(const FilePath & path)488*6777b538SAndroid Build Coastguard Worker FilePath GetUniquePath(const FilePath& path) {
489*6777b538SAndroid Build Coastguard Worker DCHECK(!path.empty());
490*6777b538SAndroid Build Coastguard Worker const int uniquifier = GetUniquePathNumber(path);
491*6777b538SAndroid Build Coastguard Worker if (uniquifier > 0)
492*6777b538SAndroid Build Coastguard Worker return path.InsertBeforeExtensionASCII(StringPrintf(" (%d)", uniquifier));
493*6777b538SAndroid Build Coastguard Worker return uniquifier == 0 ? path : FilePath();
494*6777b538SAndroid Build Coastguard Worker }
495*6777b538SAndroid Build Coastguard Worker
496*6777b538SAndroid Build Coastguard Worker } // namespace base
497