xref: /aosp_15_r20/external/cronet/base/files/file_util.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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