xref: /aosp_15_r20/external/cronet/base/files/file_util_win.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 <windows.h>
8*6777b538SAndroid Build Coastguard Worker #include <winsock2.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <io.h>
11*6777b538SAndroid Build Coastguard Worker #include <psapi.h>
12*6777b538SAndroid Build Coastguard Worker #include <shellapi.h>
13*6777b538SAndroid Build Coastguard Worker #include <shlobj.h>
14*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
15*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
16*6777b538SAndroid Build Coastguard Worker #include <time.h>
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker #include <algorithm>
19*6777b538SAndroid Build Coastguard Worker #include <limits>
20*6777b538SAndroid Build Coastguard Worker #include <string>
21*6777b538SAndroid Build Coastguard Worker #include <utility>
22*6777b538SAndroid Build Coastguard Worker #include <vector>
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/clang_profiling_buildflags.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/debug/alias.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/feature_list.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/features.h"
29*6777b538SAndroid Build Coastguard Worker #include "base/files/file_enumerator.h"
30*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h"
31*6777b538SAndroid Build Coastguard Worker #include "base/files/memory_mapped_file.h"
32*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
33*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
34*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
35*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
36*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions.h"
37*6777b538SAndroid Build Coastguard Worker #include "base/path_service.h"
38*6777b538SAndroid Build Coastguard Worker #include "base/process/process_handle.h"
39*6777b538SAndroid Build Coastguard Worker #include "base/rand_util.h"
40*6777b538SAndroid Build Coastguard Worker #include "base/strings/strcat.h"
41*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
42*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
43*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
44*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util_win.h"
45*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
46*6777b538SAndroid Build Coastguard Worker #include "base/task/bind_post_task.h"
47*6777b538SAndroid Build Coastguard Worker #include "base/task/sequenced_task_runner.h"
48*6777b538SAndroid Build Coastguard Worker #include "base/task/thread_pool.h"
49*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call.h"
50*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_thread_priority.h"
51*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
52*6777b538SAndroid Build Coastguard Worker #include "base/uuid.h"
53*6777b538SAndroid Build Coastguard Worker #include "base/win/scoped_handle.h"
54*6777b538SAndroid Build Coastguard Worker #include "base/win/security_util.h"
55*6777b538SAndroid Build Coastguard Worker #include "base/win/sid.h"
56*6777b538SAndroid Build Coastguard Worker #include "base/win/windows_types.h"
57*6777b538SAndroid Build Coastguard Worker #include "base/win/windows_version.h"
58*6777b538SAndroid Build Coastguard Worker 
59*6777b538SAndroid Build Coastguard Worker namespace base {
60*6777b538SAndroid Build Coastguard Worker 
61*6777b538SAndroid Build Coastguard Worker namespace {
62*6777b538SAndroid Build Coastguard Worker 
63*6777b538SAndroid Build Coastguard Worker int g_extra_allowed_path_for_no_execute = 0;
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker bool g_disable_secure_system_temp_for_testing = false;
66*6777b538SAndroid Build Coastguard Worker 
67*6777b538SAndroid Build Coastguard Worker const DWORD kFileShareAll =
68*6777b538SAndroid Build Coastguard Worker     FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
69*6777b538SAndroid Build Coastguard Worker const wchar_t kDefaultTempDirPrefix[] = L"ChromiumTemp";
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker // Returns the Win32 last error code or ERROR_SUCCESS if the last error code is
72*6777b538SAndroid Build Coastguard Worker // ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND. This is useful in cases where
73*6777b538SAndroid Build Coastguard Worker // the absence of a file or path is a success condition (e.g., when attempting
74*6777b538SAndroid Build Coastguard Worker // to delete an item in the filesystem).
ReturnLastErrorOrSuccessOnNotFound()75*6777b538SAndroid Build Coastguard Worker DWORD ReturnLastErrorOrSuccessOnNotFound() {
76*6777b538SAndroid Build Coastguard Worker   const DWORD error_code = ::GetLastError();
77*6777b538SAndroid Build Coastguard Worker   return (error_code == ERROR_FILE_NOT_FOUND ||
78*6777b538SAndroid Build Coastguard Worker           error_code == ERROR_PATH_NOT_FOUND)
79*6777b538SAndroid Build Coastguard Worker              ? ERROR_SUCCESS
80*6777b538SAndroid Build Coastguard Worker              : error_code;
81*6777b538SAndroid Build Coastguard Worker }
82*6777b538SAndroid Build Coastguard Worker 
83*6777b538SAndroid Build Coastguard Worker // Deletes all files and directories in a path.
84*6777b538SAndroid Build Coastguard Worker // Returns ERROR_SUCCESS on success or the Windows error code corresponding to
85*6777b538SAndroid Build Coastguard Worker // the first error encountered. ERROR_FILE_NOT_FOUND and ERROR_PATH_NOT_FOUND
86*6777b538SAndroid Build Coastguard Worker // are considered success conditions, and are therefore never returned.
DeleteFileRecursive(const FilePath & path,const FilePath::StringType & pattern,bool recursive)87*6777b538SAndroid Build Coastguard Worker DWORD DeleteFileRecursive(const FilePath& path,
88*6777b538SAndroid Build Coastguard Worker                           const FilePath::StringType& pattern,
89*6777b538SAndroid Build Coastguard Worker                           bool recursive) {
90*6777b538SAndroid Build Coastguard Worker   FileEnumerator traversal(path, false,
91*6777b538SAndroid Build Coastguard Worker                            FileEnumerator::FILES | FileEnumerator::DIRECTORIES,
92*6777b538SAndroid Build Coastguard Worker                            pattern);
93*6777b538SAndroid Build Coastguard Worker   DWORD result = ERROR_SUCCESS;
94*6777b538SAndroid Build Coastguard Worker   for (FilePath current = traversal.Next(); !current.empty();
95*6777b538SAndroid Build Coastguard Worker        current = traversal.Next()) {
96*6777b538SAndroid Build Coastguard Worker     // Try to clear the read-only bit if we find it.
97*6777b538SAndroid Build Coastguard Worker     FileEnumerator::FileInfo info = traversal.GetInfo();
98*6777b538SAndroid Build Coastguard Worker     if ((info.find_data().dwFileAttributes & FILE_ATTRIBUTE_READONLY) &&
99*6777b538SAndroid Build Coastguard Worker         (recursive || !info.IsDirectory())) {
100*6777b538SAndroid Build Coastguard Worker       ::SetFileAttributes(
101*6777b538SAndroid Build Coastguard Worker           current.value().c_str(),
102*6777b538SAndroid Build Coastguard Worker           info.find_data().dwFileAttributes & ~DWORD{FILE_ATTRIBUTE_READONLY});
103*6777b538SAndroid Build Coastguard Worker     }
104*6777b538SAndroid Build Coastguard Worker 
105*6777b538SAndroid Build Coastguard Worker     DWORD this_result = ERROR_SUCCESS;
106*6777b538SAndroid Build Coastguard Worker     if (info.IsDirectory()) {
107*6777b538SAndroid Build Coastguard Worker       if (recursive) {
108*6777b538SAndroid Build Coastguard Worker         this_result = DeleteFileRecursive(current, pattern, true);
109*6777b538SAndroid Build Coastguard Worker         DCHECK_NE(static_cast<LONG>(this_result), ERROR_FILE_NOT_FOUND);
110*6777b538SAndroid Build Coastguard Worker         DCHECK_NE(static_cast<LONG>(this_result), ERROR_PATH_NOT_FOUND);
111*6777b538SAndroid Build Coastguard Worker         if (this_result == ERROR_SUCCESS &&
112*6777b538SAndroid Build Coastguard Worker             !::RemoveDirectory(current.value().c_str())) {
113*6777b538SAndroid Build Coastguard Worker           this_result = ReturnLastErrorOrSuccessOnNotFound();
114*6777b538SAndroid Build Coastguard Worker         }
115*6777b538SAndroid Build Coastguard Worker       }
116*6777b538SAndroid Build Coastguard Worker     } else if (!::DeleteFile(current.value().c_str())) {
117*6777b538SAndroid Build Coastguard Worker       this_result = ReturnLastErrorOrSuccessOnNotFound();
118*6777b538SAndroid Build Coastguard Worker     }
119*6777b538SAndroid Build Coastguard Worker     if (result == ERROR_SUCCESS)
120*6777b538SAndroid Build Coastguard Worker       result = this_result;
121*6777b538SAndroid Build Coastguard Worker   }
122*6777b538SAndroid Build Coastguard Worker   return result;
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker // Appends |mode_char| to |mode| before the optional character set encoding; see
126*6777b538SAndroid Build Coastguard Worker // https://msdn.microsoft.com/library/yeby3zcb.aspx for details.
AppendModeCharacter(wchar_t mode_char,std::wstring * mode)127*6777b538SAndroid Build Coastguard Worker void AppendModeCharacter(wchar_t mode_char, std::wstring* mode) {
128*6777b538SAndroid Build Coastguard Worker   size_t comma_pos = mode->find(L',');
129*6777b538SAndroid Build Coastguard Worker   mode->insert(comma_pos == std::wstring::npos ? mode->length() : comma_pos, 1,
130*6777b538SAndroid Build Coastguard Worker                mode_char);
131*6777b538SAndroid Build Coastguard Worker }
132*6777b538SAndroid Build Coastguard Worker 
DoCopyFile(const FilePath & from_path,const FilePath & to_path,bool fail_if_exists)133*6777b538SAndroid Build Coastguard Worker bool DoCopyFile(const FilePath& from_path,
134*6777b538SAndroid Build Coastguard Worker                 const FilePath& to_path,
135*6777b538SAndroid Build Coastguard Worker                 bool fail_if_exists) {
136*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
137*6777b538SAndroid Build Coastguard Worker   if (from_path.ReferencesParent() || to_path.ReferencesParent())
138*6777b538SAndroid Build Coastguard Worker     return false;
139*6777b538SAndroid Build Coastguard Worker 
140*6777b538SAndroid Build Coastguard Worker   // NOTE: I suspect we could support longer paths, but that would involve
141*6777b538SAndroid Build Coastguard Worker   // analyzing all our usage of files.
142*6777b538SAndroid Build Coastguard Worker   if (from_path.value().length() >= MAX_PATH ||
143*6777b538SAndroid Build Coastguard Worker       to_path.value().length() >= MAX_PATH) {
144*6777b538SAndroid Build Coastguard Worker     return false;
145*6777b538SAndroid Build Coastguard Worker   }
146*6777b538SAndroid Build Coastguard Worker 
147*6777b538SAndroid Build Coastguard Worker   // Mitigate the issues caused by loading DLLs on a background thread
148*6777b538SAndroid Build Coastguard Worker   // (http://crbug/973868).
149*6777b538SAndroid Build Coastguard Worker   SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
150*6777b538SAndroid Build Coastguard Worker 
151*6777b538SAndroid Build Coastguard Worker   // Unlike the posix implementation that copies the file manually and discards
152*6777b538SAndroid Build Coastguard Worker   // the ACL bits, CopyFile() copies the complete SECURITY_DESCRIPTOR and access
153*6777b538SAndroid Build Coastguard Worker   // bits, which is usually not what we want. We can't do much about the
154*6777b538SAndroid Build Coastguard Worker   // SECURITY_DESCRIPTOR but at least remove the read only bit.
155*6777b538SAndroid Build Coastguard Worker   const wchar_t* dest = to_path.value().c_str();
156*6777b538SAndroid Build Coastguard Worker   if (!::CopyFile(from_path.value().c_str(), dest, fail_if_exists)) {
157*6777b538SAndroid Build Coastguard Worker     // Copy failed.
158*6777b538SAndroid Build Coastguard Worker     return false;
159*6777b538SAndroid Build Coastguard Worker   }
160*6777b538SAndroid Build Coastguard Worker   DWORD attrs = GetFileAttributes(dest);
161*6777b538SAndroid Build Coastguard Worker   if (attrs == INVALID_FILE_ATTRIBUTES) {
162*6777b538SAndroid Build Coastguard Worker     return false;
163*6777b538SAndroid Build Coastguard Worker   }
164*6777b538SAndroid Build Coastguard Worker   if (attrs & FILE_ATTRIBUTE_READONLY) {
165*6777b538SAndroid Build Coastguard Worker     SetFileAttributes(dest, attrs & ~DWORD{FILE_ATTRIBUTE_READONLY});
166*6777b538SAndroid Build Coastguard Worker   }
167*6777b538SAndroid Build Coastguard Worker   return true;
168*6777b538SAndroid Build Coastguard Worker }
169*6777b538SAndroid Build Coastguard Worker 
DoCopyDirectory(const FilePath & from_path,const FilePath & to_path,bool recursive,bool fail_if_exists)170*6777b538SAndroid Build Coastguard Worker bool DoCopyDirectory(const FilePath& from_path,
171*6777b538SAndroid Build Coastguard Worker                      const FilePath& to_path,
172*6777b538SAndroid Build Coastguard Worker                      bool recursive,
173*6777b538SAndroid Build Coastguard Worker                      bool fail_if_exists) {
174*6777b538SAndroid Build Coastguard Worker   // NOTE(maruel): Previous version of this function used to call
175*6777b538SAndroid Build Coastguard Worker   // SHFileOperation().  This used to copy the file attributes and extended
176*6777b538SAndroid Build Coastguard Worker   // attributes, OLE structured storage, NTFS file system alternate data
177*6777b538SAndroid Build Coastguard Worker   // streams, SECURITY_DESCRIPTOR. In practice, this is not what we want, we
178*6777b538SAndroid Build Coastguard Worker   // want the containing directory to propagate its SECURITY_DESCRIPTOR.
179*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
180*6777b538SAndroid Build Coastguard Worker 
181*6777b538SAndroid Build Coastguard Worker   // NOTE: I suspect we could support longer paths, but that would involve
182*6777b538SAndroid Build Coastguard Worker   // analyzing all our usage of files.
183*6777b538SAndroid Build Coastguard Worker   if (from_path.value().length() >= MAX_PATH ||
184*6777b538SAndroid Build Coastguard Worker       to_path.value().length() >= MAX_PATH) {
185*6777b538SAndroid Build Coastguard Worker     return false;
186*6777b538SAndroid Build Coastguard Worker   }
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker   // This function does not properly handle destinations within the source.
189*6777b538SAndroid Build Coastguard Worker   FilePath real_to_path = to_path;
190*6777b538SAndroid Build Coastguard Worker   if (PathExists(real_to_path)) {
191*6777b538SAndroid Build Coastguard Worker     real_to_path = MakeAbsoluteFilePath(real_to_path);
192*6777b538SAndroid Build Coastguard Worker     if (real_to_path.empty())
193*6777b538SAndroid Build Coastguard Worker       return false;
194*6777b538SAndroid Build Coastguard Worker   } else {
195*6777b538SAndroid Build Coastguard Worker     real_to_path = MakeAbsoluteFilePath(real_to_path.DirName());
196*6777b538SAndroid Build Coastguard Worker     if (real_to_path.empty())
197*6777b538SAndroid Build Coastguard Worker       return false;
198*6777b538SAndroid Build Coastguard Worker   }
199*6777b538SAndroid Build Coastguard Worker   FilePath real_from_path = MakeAbsoluteFilePath(from_path);
200*6777b538SAndroid Build Coastguard Worker   if (real_from_path.empty())
201*6777b538SAndroid Build Coastguard Worker     return false;
202*6777b538SAndroid Build Coastguard Worker   if (real_to_path == real_from_path || real_from_path.IsParent(real_to_path))
203*6777b538SAndroid Build Coastguard Worker     return false;
204*6777b538SAndroid Build Coastguard Worker 
205*6777b538SAndroid Build Coastguard Worker   int traverse_type = FileEnumerator::FILES;
206*6777b538SAndroid Build Coastguard Worker   if (recursive)
207*6777b538SAndroid Build Coastguard Worker     traverse_type |= FileEnumerator::DIRECTORIES;
208*6777b538SAndroid Build Coastguard Worker   FileEnumerator traversal(from_path, recursive, traverse_type);
209*6777b538SAndroid Build Coastguard Worker 
210*6777b538SAndroid Build Coastguard Worker   if (!PathExists(from_path)) {
211*6777b538SAndroid Build Coastguard Worker     DLOG(ERROR) << "CopyDirectory() couldn't stat source directory: "
212*6777b538SAndroid Build Coastguard Worker                 << from_path.value().c_str();
213*6777b538SAndroid Build Coastguard Worker     return false;
214*6777b538SAndroid Build Coastguard Worker   }
215*6777b538SAndroid Build Coastguard Worker   // TODO(maruel): This is not necessary anymore.
216*6777b538SAndroid Build Coastguard Worker   DCHECK(recursive || DirectoryExists(from_path));
217*6777b538SAndroid Build Coastguard Worker 
218*6777b538SAndroid Build Coastguard Worker   FilePath current = from_path;
219*6777b538SAndroid Build Coastguard Worker   bool from_is_dir = DirectoryExists(from_path);
220*6777b538SAndroid Build Coastguard Worker   bool success = true;
221*6777b538SAndroid Build Coastguard Worker   FilePath from_path_base = from_path;
222*6777b538SAndroid Build Coastguard Worker   if (recursive && DirectoryExists(to_path)) {
223*6777b538SAndroid Build Coastguard Worker     // If the destination already exists and is a directory, then the
224*6777b538SAndroid Build Coastguard Worker     // top level of source needs to be copied.
225*6777b538SAndroid Build Coastguard Worker     from_path_base = from_path.DirName();
226*6777b538SAndroid Build Coastguard Worker   }
227*6777b538SAndroid Build Coastguard Worker 
228*6777b538SAndroid Build Coastguard Worker   while (success && !current.empty()) {
229*6777b538SAndroid Build Coastguard Worker     // current is the source path, including from_path, so append
230*6777b538SAndroid Build Coastguard Worker     // the suffix after from_path to to_path to create the target_path.
231*6777b538SAndroid Build Coastguard Worker     FilePath target_path(to_path);
232*6777b538SAndroid Build Coastguard Worker     if (from_path_base != current) {
233*6777b538SAndroid Build Coastguard Worker       if (!from_path_base.AppendRelativePath(current, &target_path)) {
234*6777b538SAndroid Build Coastguard Worker         success = false;
235*6777b538SAndroid Build Coastguard Worker         break;
236*6777b538SAndroid Build Coastguard Worker       }
237*6777b538SAndroid Build Coastguard Worker     }
238*6777b538SAndroid Build Coastguard Worker 
239*6777b538SAndroid Build Coastguard Worker     if (from_is_dir) {
240*6777b538SAndroid Build Coastguard Worker       if (!DirectoryExists(target_path) &&
241*6777b538SAndroid Build Coastguard Worker           !::CreateDirectory(target_path.value().c_str(), NULL)) {
242*6777b538SAndroid Build Coastguard Worker         DLOG(ERROR) << "CopyDirectory() couldn't create directory: "
243*6777b538SAndroid Build Coastguard Worker                     << target_path.value().c_str();
244*6777b538SAndroid Build Coastguard Worker         success = false;
245*6777b538SAndroid Build Coastguard Worker       }
246*6777b538SAndroid Build Coastguard Worker     } else if (!DoCopyFile(current, target_path, fail_if_exists)) {
247*6777b538SAndroid Build Coastguard Worker       DLOG(ERROR) << "CopyDirectory() couldn't create file: "
248*6777b538SAndroid Build Coastguard Worker                   << target_path.value().c_str();
249*6777b538SAndroid Build Coastguard Worker       success = false;
250*6777b538SAndroid Build Coastguard Worker     }
251*6777b538SAndroid Build Coastguard Worker 
252*6777b538SAndroid Build Coastguard Worker     current = traversal.Next();
253*6777b538SAndroid Build Coastguard Worker     if (!current.empty())
254*6777b538SAndroid Build Coastguard Worker       from_is_dir = traversal.GetInfo().IsDirectory();
255*6777b538SAndroid Build Coastguard Worker   }
256*6777b538SAndroid Build Coastguard Worker 
257*6777b538SAndroid Build Coastguard Worker   return success;
258*6777b538SAndroid Build Coastguard Worker }
259*6777b538SAndroid Build Coastguard Worker 
260*6777b538SAndroid Build Coastguard Worker // Returns ERROR_SUCCESS on success, or a Windows error code on failure.
DoDeleteFile(const FilePath & path,bool recursive)261*6777b538SAndroid Build Coastguard Worker DWORD DoDeleteFile(const FilePath& path, bool recursive) {
262*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
263*6777b538SAndroid Build Coastguard Worker 
264*6777b538SAndroid Build Coastguard Worker   if (path.empty())
265*6777b538SAndroid Build Coastguard Worker     return ERROR_SUCCESS;
266*6777b538SAndroid Build Coastguard Worker 
267*6777b538SAndroid Build Coastguard Worker   if (path.value().length() >= MAX_PATH)
268*6777b538SAndroid Build Coastguard Worker     return ERROR_BAD_PATHNAME;
269*6777b538SAndroid Build Coastguard Worker 
270*6777b538SAndroid Build Coastguard Worker   // Handle any path with wildcards.
271*6777b538SAndroid Build Coastguard Worker   if (path.BaseName().value().find_first_of(FILE_PATH_LITERAL("*?")) !=
272*6777b538SAndroid Build Coastguard Worker       FilePath::StringType::npos) {
273*6777b538SAndroid Build Coastguard Worker     const DWORD error_code =
274*6777b538SAndroid Build Coastguard Worker         DeleteFileRecursive(path.DirName(), path.BaseName().value(), recursive);
275*6777b538SAndroid Build Coastguard Worker     DCHECK_NE(static_cast<LONG>(error_code), ERROR_FILE_NOT_FOUND);
276*6777b538SAndroid Build Coastguard Worker     DCHECK_NE(static_cast<LONG>(error_code), ERROR_PATH_NOT_FOUND);
277*6777b538SAndroid Build Coastguard Worker     return error_code;
278*6777b538SAndroid Build Coastguard Worker   }
279*6777b538SAndroid Build Coastguard Worker 
280*6777b538SAndroid Build Coastguard Worker   // Report success if the file or path does not exist.
281*6777b538SAndroid Build Coastguard Worker   const DWORD attr = ::GetFileAttributes(path.value().c_str());
282*6777b538SAndroid Build Coastguard Worker   if (attr == INVALID_FILE_ATTRIBUTES)
283*6777b538SAndroid Build Coastguard Worker     return ReturnLastErrorOrSuccessOnNotFound();
284*6777b538SAndroid Build Coastguard Worker 
285*6777b538SAndroid Build Coastguard Worker   // Clear the read-only bit if it is set.
286*6777b538SAndroid Build Coastguard Worker   if ((attr & FILE_ATTRIBUTE_READONLY) &&
287*6777b538SAndroid Build Coastguard Worker       !::SetFileAttributes(path.value().c_str(),
288*6777b538SAndroid Build Coastguard Worker                            attr & ~DWORD{FILE_ATTRIBUTE_READONLY})) {
289*6777b538SAndroid Build Coastguard Worker     // It's possible for |path| to be gone now under a race with other deleters.
290*6777b538SAndroid Build Coastguard Worker     return ReturnLastErrorOrSuccessOnNotFound();
291*6777b538SAndroid Build Coastguard Worker   }
292*6777b538SAndroid Build Coastguard Worker 
293*6777b538SAndroid Build Coastguard Worker   // Perform a simple delete on anything that isn't a directory.
294*6777b538SAndroid Build Coastguard Worker   if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
295*6777b538SAndroid Build Coastguard Worker     return ::DeleteFile(path.value().c_str())
296*6777b538SAndroid Build Coastguard Worker                ? ERROR_SUCCESS
297*6777b538SAndroid Build Coastguard Worker                : ReturnLastErrorOrSuccessOnNotFound();
298*6777b538SAndroid Build Coastguard Worker   }
299*6777b538SAndroid Build Coastguard Worker 
300*6777b538SAndroid Build Coastguard Worker   if (recursive) {
301*6777b538SAndroid Build Coastguard Worker     const DWORD error_code =
302*6777b538SAndroid Build Coastguard Worker         DeleteFileRecursive(path, FILE_PATH_LITERAL("*"), true);
303*6777b538SAndroid Build Coastguard Worker     DCHECK_NE(static_cast<LONG>(error_code), ERROR_FILE_NOT_FOUND);
304*6777b538SAndroid Build Coastguard Worker     DCHECK_NE(static_cast<LONG>(error_code), ERROR_PATH_NOT_FOUND);
305*6777b538SAndroid Build Coastguard Worker     if (error_code != ERROR_SUCCESS)
306*6777b538SAndroid Build Coastguard Worker       return error_code;
307*6777b538SAndroid Build Coastguard Worker   }
308*6777b538SAndroid Build Coastguard Worker   return ::RemoveDirectory(path.value().c_str())
309*6777b538SAndroid Build Coastguard Worker              ? ERROR_SUCCESS
310*6777b538SAndroid Build Coastguard Worker              : ReturnLastErrorOrSuccessOnNotFound();
311*6777b538SAndroid Build Coastguard Worker }
312*6777b538SAndroid Build Coastguard Worker 
313*6777b538SAndroid Build Coastguard Worker // Deletes the file/directory at |path| (recursively if |recursive| and |path|
314*6777b538SAndroid Build Coastguard Worker // names a directory), returning true on success. Sets the Windows last-error
315*6777b538SAndroid Build Coastguard Worker // code and returns false on failure.
DeleteFileOrSetLastError(const FilePath & path,bool recursive)316*6777b538SAndroid Build Coastguard Worker bool DeleteFileOrSetLastError(const FilePath& path, bool recursive) {
317*6777b538SAndroid Build Coastguard Worker   const DWORD error = DoDeleteFile(path, recursive);
318*6777b538SAndroid Build Coastguard Worker   if (error == ERROR_SUCCESS)
319*6777b538SAndroid Build Coastguard Worker     return true;
320*6777b538SAndroid Build Coastguard Worker 
321*6777b538SAndroid Build Coastguard Worker   ::SetLastError(error);
322*6777b538SAndroid Build Coastguard Worker   return false;
323*6777b538SAndroid Build Coastguard Worker }
324*6777b538SAndroid Build Coastguard Worker 
325*6777b538SAndroid Build Coastguard Worker constexpr int kMaxDeleteAttempts = 9;
326*6777b538SAndroid Build Coastguard Worker 
DeleteFileWithRetry(const FilePath & path,bool recursive,int attempt,OnceCallback<void (bool)> reply_callback)327*6777b538SAndroid Build Coastguard Worker void DeleteFileWithRetry(const FilePath& path,
328*6777b538SAndroid Build Coastguard Worker                          bool recursive,
329*6777b538SAndroid Build Coastguard Worker                          int attempt,
330*6777b538SAndroid Build Coastguard Worker                          OnceCallback<void(bool)> reply_callback) {
331*6777b538SAndroid Build Coastguard Worker   // Retry every 250ms for up to two seconds. These values were pulled out of
332*6777b538SAndroid Build Coastguard Worker   // thin air, and may be adjusted in the future based on the metrics collected.
333*6777b538SAndroid Build Coastguard Worker   static constexpr TimeDelta kDeleteFileRetryDelay = Milliseconds(250);
334*6777b538SAndroid Build Coastguard Worker 
335*6777b538SAndroid Build Coastguard Worker   if (DeleteFileOrSetLastError(path, recursive)) {
336*6777b538SAndroid Build Coastguard Worker     // Consider introducing further retries until the item has been removed from
337*6777b538SAndroid Build Coastguard Worker     // the filesystem and its name is ready for reuse; see the comments in
338*6777b538SAndroid Build Coastguard Worker     // chrome/installer/mini_installer/delete_with_retry.cc for details.
339*6777b538SAndroid Build Coastguard Worker     if (!reply_callback.is_null())
340*6777b538SAndroid Build Coastguard Worker       std::move(reply_callback).Run(true);
341*6777b538SAndroid Build Coastguard Worker     return;
342*6777b538SAndroid Build Coastguard Worker   }
343*6777b538SAndroid Build Coastguard Worker 
344*6777b538SAndroid Build Coastguard Worker   ++attempt;
345*6777b538SAndroid Build Coastguard Worker   DCHECK_LE(attempt, kMaxDeleteAttempts);
346*6777b538SAndroid Build Coastguard Worker   if (attempt == kMaxDeleteAttempts) {
347*6777b538SAndroid Build Coastguard Worker     if (!reply_callback.is_null())
348*6777b538SAndroid Build Coastguard Worker       std::move(reply_callback).Run(false);
349*6777b538SAndroid Build Coastguard Worker     return;
350*6777b538SAndroid Build Coastguard Worker   }
351*6777b538SAndroid Build Coastguard Worker 
352*6777b538SAndroid Build Coastguard Worker   ThreadPool::PostDelayedTask(FROM_HERE,
353*6777b538SAndroid Build Coastguard Worker                               {TaskPriority::BEST_EFFORT, MayBlock()},
354*6777b538SAndroid Build Coastguard Worker                               BindOnce(&DeleteFileWithRetry, path, recursive,
355*6777b538SAndroid Build Coastguard Worker                                        attempt, std::move(reply_callback)),
356*6777b538SAndroid Build Coastguard Worker                               kDeleteFileRetryDelay);
357*6777b538SAndroid Build Coastguard Worker }
358*6777b538SAndroid Build Coastguard Worker 
GetDeleteFileCallbackInternal(const FilePath & path,bool recursive,OnceCallback<void (bool)> reply_callback)359*6777b538SAndroid Build Coastguard Worker OnceClosure GetDeleteFileCallbackInternal(
360*6777b538SAndroid Build Coastguard Worker     const FilePath& path,
361*6777b538SAndroid Build Coastguard Worker     bool recursive,
362*6777b538SAndroid Build Coastguard Worker     OnceCallback<void(bool)> reply_callback) {
363*6777b538SAndroid Build Coastguard Worker   OnceCallback<void(bool)> bound_callback;
364*6777b538SAndroid Build Coastguard Worker   if (!reply_callback.is_null()) {
365*6777b538SAndroid Build Coastguard Worker     bound_callback = BindPostTask(SequencedTaskRunner::GetCurrentDefault(),
366*6777b538SAndroid Build Coastguard Worker                                   std::move(reply_callback));
367*6777b538SAndroid Build Coastguard Worker   }
368*6777b538SAndroid Build Coastguard Worker   return BindOnce(&DeleteFileWithRetry, path, recursive, /*attempt=*/0,
369*6777b538SAndroid Build Coastguard Worker                   std::move(bound_callback));
370*6777b538SAndroid Build Coastguard Worker }
371*6777b538SAndroid Build Coastguard Worker 
372*6777b538SAndroid Build Coastguard Worker // This function verifies that no code is attempting to set an ACL on a file
373*6777b538SAndroid Build Coastguard Worker // that is outside of 'safe' paths. A 'safe' path is defined as one that is
374*6777b538SAndroid Build Coastguard Worker // within the user data dir, or the temporary directory. This is explicitly to
375*6777b538SAndroid Build Coastguard Worker // prevent code from trying to pass a writeable handle to a file outside of
376*6777b538SAndroid Build Coastguard Worker // these directories to an untrusted process. E.g. if some future code created a
377*6777b538SAndroid Build Coastguard Worker // writeable handle to a file in c:\users\user\sensitive.dat, this DCHECK would
378*6777b538SAndroid Build Coastguard Worker // hit. Setting an ACL on a file outside of these chrome-controlled directories
379*6777b538SAndroid Build Coastguard Worker // might cause the browser or operating system to fail in unexpected ways.
IsPathSafeToSetAclOn(const FilePath & path)380*6777b538SAndroid Build Coastguard Worker bool IsPathSafeToSetAclOn(const FilePath& path) {
381*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(CLANG_PROFILING)
382*6777b538SAndroid Build Coastguard Worker   // TODO(crbug.com/329482479) Use PreventExecuteMappingUnchecked for .profraw.
383*6777b538SAndroid Build Coastguard Worker   // Ignore .profraw profiling files, as they can occur anywhere, and only occur
384*6777b538SAndroid Build Coastguard Worker   // during testing.
385*6777b538SAndroid Build Coastguard Worker   if (path.Extension() == FILE_PATH_LITERAL(".profraw")) {
386*6777b538SAndroid Build Coastguard Worker     return true;
387*6777b538SAndroid Build Coastguard Worker   }
388*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(CLANG_PROFILING)
389*6777b538SAndroid Build Coastguard Worker   std::vector<int> valid_path_keys({DIR_TEMP});
390*6777b538SAndroid Build Coastguard Worker   if (g_extra_allowed_path_for_no_execute) {
391*6777b538SAndroid Build Coastguard Worker     valid_path_keys.push_back(g_extra_allowed_path_for_no_execute);
392*6777b538SAndroid Build Coastguard Worker   }
393*6777b538SAndroid Build Coastguard Worker 
394*6777b538SAndroid Build Coastguard Worker   // MakeLongFilePath is needed here because temp files can have an 8.3 path
395*6777b538SAndroid Build Coastguard Worker   // under certain conditions. See comments in base::MakeLongFilePath.
396*6777b538SAndroid Build Coastguard Worker   FilePath long_path = MakeLongFilePath(path);
397*6777b538SAndroid Build Coastguard Worker   DCHECK(!long_path.empty()) << "Cannot get long path for " << path;
398*6777b538SAndroid Build Coastguard Worker 
399*6777b538SAndroid Build Coastguard Worker   std::vector<FilePath> valid_paths;
400*6777b538SAndroid Build Coastguard Worker   for (const auto path_key : valid_path_keys) {
401*6777b538SAndroid Build Coastguard Worker     FilePath valid_path;
402*6777b538SAndroid Build Coastguard Worker     if (!PathService::Get(path_key, &valid_path)) {
403*6777b538SAndroid Build Coastguard Worker       DLOG(FATAL) << "Cannot get path for pathservice key " << path_key;
404*6777b538SAndroid Build Coastguard Worker       continue;
405*6777b538SAndroid Build Coastguard Worker     }
406*6777b538SAndroid Build Coastguard Worker     valid_paths.push_back(valid_path);
407*6777b538SAndroid Build Coastguard Worker   }
408*6777b538SAndroid Build Coastguard Worker 
409*6777b538SAndroid Build Coastguard Worker   // Admin users create temporary files in `GetSecureSystemTemp`, see
410*6777b538SAndroid Build Coastguard Worker   // `CreateNewTempDirectory` below.
411*6777b538SAndroid Build Coastguard Worker   FilePath secure_system_temp;
412*6777b538SAndroid Build Coastguard Worker   if (::IsUserAnAdmin() && GetSecureSystemTemp(&secure_system_temp)) {
413*6777b538SAndroid Build Coastguard Worker     valid_paths.push_back(secure_system_temp);
414*6777b538SAndroid Build Coastguard Worker   }
415*6777b538SAndroid Build Coastguard Worker 
416*6777b538SAndroid Build Coastguard Worker   for (const auto& valid_path : valid_paths) {
417*6777b538SAndroid Build Coastguard Worker     // Temp files can sometimes have an 8.3 path. See comments in
418*6777b538SAndroid Build Coastguard Worker     // `MakeLongFilePath`.
419*6777b538SAndroid Build Coastguard Worker     FilePath full_path = MakeLongFilePath(valid_path);
420*6777b538SAndroid Build Coastguard Worker     DCHECK(!full_path.empty()) << "Cannot get long path for " << valid_path;
421*6777b538SAndroid Build Coastguard Worker     if (full_path.IsParent(long_path)) {
422*6777b538SAndroid Build Coastguard Worker       return true;
423*6777b538SAndroid Build Coastguard Worker     }
424*6777b538SAndroid Build Coastguard Worker   }
425*6777b538SAndroid Build Coastguard Worker 
426*6777b538SAndroid Build Coastguard Worker   return false;
427*6777b538SAndroid Build Coastguard Worker }
428*6777b538SAndroid Build Coastguard Worker 
429*6777b538SAndroid Build Coastguard Worker }  // namespace
430*6777b538SAndroid Build Coastguard Worker 
GetDeleteFileCallback(const FilePath & path,OnceCallback<void (bool)> reply_callback)431*6777b538SAndroid Build Coastguard Worker OnceClosure GetDeleteFileCallback(const FilePath& path,
432*6777b538SAndroid Build Coastguard Worker                                   OnceCallback<void(bool)> reply_callback) {
433*6777b538SAndroid Build Coastguard Worker   return GetDeleteFileCallbackInternal(path, /*recursive=*/false,
434*6777b538SAndroid Build Coastguard Worker                                        std::move(reply_callback));
435*6777b538SAndroid Build Coastguard Worker }
436*6777b538SAndroid Build Coastguard Worker 
GetDeletePathRecursivelyCallback(const FilePath & path,OnceCallback<void (bool)> reply_callback)437*6777b538SAndroid Build Coastguard Worker OnceClosure GetDeletePathRecursivelyCallback(
438*6777b538SAndroid Build Coastguard Worker     const FilePath& path,
439*6777b538SAndroid Build Coastguard Worker     OnceCallback<void(bool)> reply_callback) {
440*6777b538SAndroid Build Coastguard Worker   return GetDeleteFileCallbackInternal(path, /*recursive=*/true,
441*6777b538SAndroid Build Coastguard Worker                                        std::move(reply_callback));
442*6777b538SAndroid Build Coastguard Worker }
443*6777b538SAndroid Build Coastguard Worker 
MakeAbsoluteFilePath(const FilePath & input)444*6777b538SAndroid Build Coastguard Worker FilePath MakeAbsoluteFilePath(const FilePath& input) {
445*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
446*6777b538SAndroid Build Coastguard Worker   wchar_t file_path[MAX_PATH];
447*6777b538SAndroid Build Coastguard Worker   if (!_wfullpath(file_path, input.value().c_str(), MAX_PATH))
448*6777b538SAndroid Build Coastguard Worker     return FilePath();
449*6777b538SAndroid Build Coastguard Worker   return FilePath(file_path);
450*6777b538SAndroid Build Coastguard Worker }
451*6777b538SAndroid Build Coastguard Worker 
DeleteFile(const FilePath & path)452*6777b538SAndroid Build Coastguard Worker bool DeleteFile(const FilePath& path) {
453*6777b538SAndroid Build Coastguard Worker   return DeleteFileOrSetLastError(path, /*recursive=*/false);
454*6777b538SAndroid Build Coastguard Worker }
455*6777b538SAndroid Build Coastguard Worker 
DeletePathRecursively(const FilePath & path)456*6777b538SAndroid Build Coastguard Worker bool DeletePathRecursively(const FilePath& path) {
457*6777b538SAndroid Build Coastguard Worker   return DeleteFileOrSetLastError(path, /*recursive=*/true);
458*6777b538SAndroid Build Coastguard Worker }
459*6777b538SAndroid Build Coastguard Worker 
DeleteFileAfterReboot(const FilePath & path)460*6777b538SAndroid Build Coastguard Worker bool DeleteFileAfterReboot(const FilePath& path) {
461*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
462*6777b538SAndroid Build Coastguard Worker 
463*6777b538SAndroid Build Coastguard Worker   if (path.value().length() >= MAX_PATH)
464*6777b538SAndroid Build Coastguard Worker     return false;
465*6777b538SAndroid Build Coastguard Worker 
466*6777b538SAndroid Build Coastguard Worker   return ::MoveFileEx(path.value().c_str(), nullptr,
467*6777b538SAndroid Build Coastguard Worker                       MOVEFILE_DELAY_UNTIL_REBOOT);
468*6777b538SAndroid Build Coastguard Worker }
469*6777b538SAndroid Build Coastguard Worker 
ReplaceFile(const FilePath & from_path,const FilePath & to_path,File::Error * error)470*6777b538SAndroid Build Coastguard Worker bool ReplaceFile(const FilePath& from_path,
471*6777b538SAndroid Build Coastguard Worker                  const FilePath& to_path,
472*6777b538SAndroid Build Coastguard Worker                  File::Error* error) {
473*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
474*6777b538SAndroid Build Coastguard Worker 
475*6777b538SAndroid Build Coastguard Worker   // Alias paths for investigation of shutdown hangs. crbug.com/1054164
476*6777b538SAndroid Build Coastguard Worker   FilePath::CharType from_path_str[MAX_PATH];
477*6777b538SAndroid Build Coastguard Worker   base::wcslcpy(from_path_str, from_path.value().c_str(),
478*6777b538SAndroid Build Coastguard Worker                 std::size(from_path_str));
479*6777b538SAndroid Build Coastguard Worker   base::debug::Alias(from_path_str);
480*6777b538SAndroid Build Coastguard Worker   FilePath::CharType to_path_str[MAX_PATH];
481*6777b538SAndroid Build Coastguard Worker   base::wcslcpy(to_path_str, to_path.value().c_str(), std::size(to_path_str));
482*6777b538SAndroid Build Coastguard Worker   base::debug::Alias(to_path_str);
483*6777b538SAndroid Build Coastguard Worker 
484*6777b538SAndroid Build Coastguard Worker   // Assume that |to_path| already exists and try the normal replace. This will
485*6777b538SAndroid Build Coastguard Worker   // fail with ERROR_FILE_NOT_FOUND if |to_path| does not exist. When writing to
486*6777b538SAndroid Build Coastguard Worker   // a network share, we may not be able to change the ACLs. Ignore ACL errors
487*6777b538SAndroid Build Coastguard Worker   // then (REPLACEFILE_IGNORE_MERGE_ERRORS).
488*6777b538SAndroid Build Coastguard Worker   if (::ReplaceFile(to_path.value().c_str(), from_path.value().c_str(), NULL,
489*6777b538SAndroid Build Coastguard Worker                     REPLACEFILE_IGNORE_MERGE_ERRORS, NULL, NULL)) {
490*6777b538SAndroid Build Coastguard Worker     return true;
491*6777b538SAndroid Build Coastguard Worker   }
492*6777b538SAndroid Build Coastguard Worker 
493*6777b538SAndroid Build Coastguard Worker   File::Error replace_error = File::OSErrorToFileError(GetLastError());
494*6777b538SAndroid Build Coastguard Worker 
495*6777b538SAndroid Build Coastguard Worker   // Try a simple move next. It will only succeed when |to_path| doesn't already
496*6777b538SAndroid Build Coastguard Worker   // exist.
497*6777b538SAndroid Build Coastguard Worker   if (::MoveFile(from_path.value().c_str(), to_path.value().c_str()))
498*6777b538SAndroid Build Coastguard Worker     return true;
499*6777b538SAndroid Build Coastguard Worker 
500*6777b538SAndroid Build Coastguard Worker   // In the case of FILE_ERROR_NOT_FOUND from ReplaceFile, it is likely that
501*6777b538SAndroid Build Coastguard Worker   // |to_path| does not exist. In this case, the more relevant error comes
502*6777b538SAndroid Build Coastguard Worker   // from the call to MoveFile.
503*6777b538SAndroid Build Coastguard Worker   if (error) {
504*6777b538SAndroid Build Coastguard Worker     *error = replace_error == File::FILE_ERROR_NOT_FOUND
505*6777b538SAndroid Build Coastguard Worker                  ? File::GetLastFileError()
506*6777b538SAndroid Build Coastguard Worker                  : replace_error;
507*6777b538SAndroid Build Coastguard Worker   }
508*6777b538SAndroid Build Coastguard Worker   return false;
509*6777b538SAndroid Build Coastguard Worker }
510*6777b538SAndroid Build Coastguard Worker 
CopyDirectory(const FilePath & from_path,const FilePath & to_path,bool recursive)511*6777b538SAndroid Build Coastguard Worker bool CopyDirectory(const FilePath& from_path,
512*6777b538SAndroid Build Coastguard Worker                    const FilePath& to_path,
513*6777b538SAndroid Build Coastguard Worker                    bool recursive) {
514*6777b538SAndroid Build Coastguard Worker   return DoCopyDirectory(from_path, to_path, recursive, false);
515*6777b538SAndroid Build Coastguard Worker }
516*6777b538SAndroid Build Coastguard Worker 
CopyDirectoryExcl(const FilePath & from_path,const FilePath & to_path,bool recursive)517*6777b538SAndroid Build Coastguard Worker bool CopyDirectoryExcl(const FilePath& from_path,
518*6777b538SAndroid Build Coastguard Worker                        const FilePath& to_path,
519*6777b538SAndroid Build Coastguard Worker                        bool recursive) {
520*6777b538SAndroid Build Coastguard Worker   return DoCopyDirectory(from_path, to_path, recursive, true);
521*6777b538SAndroid Build Coastguard Worker }
522*6777b538SAndroid Build Coastguard Worker 
PathExists(const FilePath & path)523*6777b538SAndroid Build Coastguard Worker bool PathExists(const FilePath& path) {
524*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
525*6777b538SAndroid Build Coastguard Worker   return (GetFileAttributes(path.value().c_str()) != INVALID_FILE_ATTRIBUTES);
526*6777b538SAndroid Build Coastguard Worker }
527*6777b538SAndroid Build Coastguard Worker 
528*6777b538SAndroid Build Coastguard Worker namespace {
529*6777b538SAndroid Build Coastguard Worker 
PathHasAccess(const FilePath & path,DWORD dir_desired_access,DWORD file_desired_access)530*6777b538SAndroid Build Coastguard Worker bool PathHasAccess(const FilePath& path,
531*6777b538SAndroid Build Coastguard Worker                    DWORD dir_desired_access,
532*6777b538SAndroid Build Coastguard Worker                    DWORD file_desired_access) {
533*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
534*6777b538SAndroid Build Coastguard Worker 
535*6777b538SAndroid Build Coastguard Worker   const wchar_t* const path_str = path.value().c_str();
536*6777b538SAndroid Build Coastguard Worker   DWORD fileattr = GetFileAttributes(path_str);
537*6777b538SAndroid Build Coastguard Worker   if (fileattr == INVALID_FILE_ATTRIBUTES)
538*6777b538SAndroid Build Coastguard Worker     return false;
539*6777b538SAndroid Build Coastguard Worker 
540*6777b538SAndroid Build Coastguard Worker   bool is_directory = fileattr & FILE_ATTRIBUTE_DIRECTORY;
541*6777b538SAndroid Build Coastguard Worker   DWORD desired_access =
542*6777b538SAndroid Build Coastguard Worker       is_directory ? dir_desired_access : file_desired_access;
543*6777b538SAndroid Build Coastguard Worker   DWORD flags_and_attrs =
544*6777b538SAndroid Build Coastguard Worker       is_directory ? FILE_FLAG_BACKUP_SEMANTICS : FILE_ATTRIBUTE_NORMAL;
545*6777b538SAndroid Build Coastguard Worker 
546*6777b538SAndroid Build Coastguard Worker   win::ScopedHandle file(CreateFile(path_str, desired_access, kFileShareAll,
547*6777b538SAndroid Build Coastguard Worker                                     nullptr, OPEN_EXISTING, flags_and_attrs,
548*6777b538SAndroid Build Coastguard Worker                                     nullptr));
549*6777b538SAndroid Build Coastguard Worker 
550*6777b538SAndroid Build Coastguard Worker   return file.is_valid();
551*6777b538SAndroid Build Coastguard Worker }
552*6777b538SAndroid Build Coastguard Worker 
553*6777b538SAndroid Build Coastguard Worker }  // namespace
554*6777b538SAndroid Build Coastguard Worker 
PathIsReadable(const FilePath & path)555*6777b538SAndroid Build Coastguard Worker bool PathIsReadable(const FilePath& path) {
556*6777b538SAndroid Build Coastguard Worker   return PathHasAccess(path, FILE_LIST_DIRECTORY, GENERIC_READ);
557*6777b538SAndroid Build Coastguard Worker }
558*6777b538SAndroid Build Coastguard Worker 
PathIsWritable(const FilePath & path)559*6777b538SAndroid Build Coastguard Worker bool PathIsWritable(const FilePath& path) {
560*6777b538SAndroid Build Coastguard Worker   return PathHasAccess(path, FILE_ADD_FILE, GENERIC_WRITE);
561*6777b538SAndroid Build Coastguard Worker }
562*6777b538SAndroid Build Coastguard Worker 
DirectoryExists(const FilePath & path)563*6777b538SAndroid Build Coastguard Worker bool DirectoryExists(const FilePath& path) {
564*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
565*6777b538SAndroid Build Coastguard Worker   DWORD fileattr = GetFileAttributes(path.value().c_str());
566*6777b538SAndroid Build Coastguard Worker   if (fileattr != INVALID_FILE_ATTRIBUTES)
567*6777b538SAndroid Build Coastguard Worker     return (fileattr & FILE_ATTRIBUTE_DIRECTORY) != 0;
568*6777b538SAndroid Build Coastguard Worker   return false;
569*6777b538SAndroid Build Coastguard Worker }
570*6777b538SAndroid Build Coastguard Worker 
GetTempDir(FilePath * path)571*6777b538SAndroid Build Coastguard Worker bool GetTempDir(FilePath* path) {
572*6777b538SAndroid Build Coastguard Worker   wchar_t temp_path[MAX_PATH + 1];
573*6777b538SAndroid Build Coastguard Worker   DWORD path_len = ::GetTempPath(MAX_PATH, temp_path);
574*6777b538SAndroid Build Coastguard Worker   if (path_len >= MAX_PATH || path_len <= 0)
575*6777b538SAndroid Build Coastguard Worker     return false;
576*6777b538SAndroid Build Coastguard Worker   // TODO(evanm): the old behavior of this function was to always strip the
577*6777b538SAndroid Build Coastguard Worker   // trailing slash.  We duplicate this here, but it shouldn't be necessary
578*6777b538SAndroid Build Coastguard Worker   // when everyone is using the appropriate FilePath APIs.
579*6777b538SAndroid Build Coastguard Worker   *path = FilePath(temp_path).StripTrailingSeparators();
580*6777b538SAndroid Build Coastguard Worker   return true;
581*6777b538SAndroid Build Coastguard Worker }
582*6777b538SAndroid Build Coastguard Worker 
GetHomeDir()583*6777b538SAndroid Build Coastguard Worker FilePath GetHomeDir() {
584*6777b538SAndroid Build Coastguard Worker   wchar_t result[MAX_PATH];
585*6777b538SAndroid Build Coastguard Worker   if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT,
586*6777b538SAndroid Build Coastguard Worker                                 result)) &&
587*6777b538SAndroid Build Coastguard Worker       result[0]) {
588*6777b538SAndroid Build Coastguard Worker     return FilePath(result);
589*6777b538SAndroid Build Coastguard Worker   }
590*6777b538SAndroid Build Coastguard Worker 
591*6777b538SAndroid Build Coastguard Worker   // Fall back to the temporary directory on failure.
592*6777b538SAndroid Build Coastguard Worker   FilePath temp;
593*6777b538SAndroid Build Coastguard Worker   if (GetTempDir(&temp))
594*6777b538SAndroid Build Coastguard Worker     return temp;
595*6777b538SAndroid Build Coastguard Worker 
596*6777b538SAndroid Build Coastguard Worker   // Last resort.
597*6777b538SAndroid Build Coastguard Worker   return FilePath(FILE_PATH_LITERAL("C:\\"));
598*6777b538SAndroid Build Coastguard Worker }
599*6777b538SAndroid Build Coastguard Worker 
CreateAndOpenTemporaryFileInDir(const FilePath & dir,FilePath * temp_file)600*6777b538SAndroid Build Coastguard Worker File CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* temp_file) {
601*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
602*6777b538SAndroid Build Coastguard Worker 
603*6777b538SAndroid Build Coastguard Worker   // Open the file with exclusive r/w/d access, and allow the caller to decide
604*6777b538SAndroid Build Coastguard Worker   // to mark it for deletion upon close after the fact.
605*6777b538SAndroid Build Coastguard Worker   constexpr uint32_t kFlags = File::FLAG_CREATE | File::FLAG_READ |
606*6777b538SAndroid Build Coastguard Worker                               File::FLAG_WRITE | File::FLAG_WIN_EXCLUSIVE_READ |
607*6777b538SAndroid Build Coastguard Worker                               File::FLAG_WIN_EXCLUSIVE_WRITE |
608*6777b538SAndroid Build Coastguard Worker                               File::FLAG_CAN_DELETE_ON_CLOSE;
609*6777b538SAndroid Build Coastguard Worker 
610*6777b538SAndroid Build Coastguard Worker   // Use GUID instead of ::GetTempFileName() to generate unique file names.
611*6777b538SAndroid Build Coastguard Worker   // "Due to the algorithm used to generate file names, GetTempFileName can
612*6777b538SAndroid Build Coastguard Worker   // perform poorly when creating a large number of files with the same prefix.
613*6777b538SAndroid Build Coastguard Worker   // In such cases, it is recommended that you construct unique file names based
614*6777b538SAndroid Build Coastguard Worker   // on GUIDs."
615*6777b538SAndroid Build Coastguard Worker   // https://msdn.microsoft.com/library/windows/desktop/aa364991.aspx
616*6777b538SAndroid Build Coastguard Worker 
617*6777b538SAndroid Build Coastguard Worker   FilePath temp_name;
618*6777b538SAndroid Build Coastguard Worker   File file;
619*6777b538SAndroid Build Coastguard Worker 
620*6777b538SAndroid Build Coastguard Worker   // Although it is nearly impossible to get a duplicate name with GUID, we
621*6777b538SAndroid Build Coastguard Worker   // still use a loop here in case it happens.
622*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < 100; ++i) {
623*6777b538SAndroid Build Coastguard Worker     temp_name = dir.Append(FormatTemporaryFileName(
624*6777b538SAndroid Build Coastguard Worker         UTF8ToWide(Uuid::GenerateRandomV4().AsLowercaseString())));
625*6777b538SAndroid Build Coastguard Worker     file.Initialize(temp_name, kFlags);
626*6777b538SAndroid Build Coastguard Worker     if (file.IsValid())
627*6777b538SAndroid Build Coastguard Worker       break;
628*6777b538SAndroid Build Coastguard Worker   }
629*6777b538SAndroid Build Coastguard Worker 
630*6777b538SAndroid Build Coastguard Worker   if (!file.IsValid()) {
631*6777b538SAndroid Build Coastguard Worker     DPLOG(WARNING) << "Failed to get temporary file name in " << dir.value();
632*6777b538SAndroid Build Coastguard Worker     return file;
633*6777b538SAndroid Build Coastguard Worker   }
634*6777b538SAndroid Build Coastguard Worker 
635*6777b538SAndroid Build Coastguard Worker   wchar_t long_temp_name[MAX_PATH + 1];
636*6777b538SAndroid Build Coastguard Worker   const DWORD long_name_len =
637*6777b538SAndroid Build Coastguard Worker       GetLongPathName(temp_name.value().c_str(), long_temp_name, MAX_PATH);
638*6777b538SAndroid Build Coastguard Worker   if (long_name_len != 0 && long_name_len <= MAX_PATH) {
639*6777b538SAndroid Build Coastguard Worker     *temp_file =
640*6777b538SAndroid Build Coastguard Worker         FilePath(FilePath::StringPieceType(long_temp_name, long_name_len));
641*6777b538SAndroid Build Coastguard Worker   } else {
642*6777b538SAndroid Build Coastguard Worker     // GetLongPathName() failed, but we still have a temporary file.
643*6777b538SAndroid Build Coastguard Worker     *temp_file = std::move(temp_name);
644*6777b538SAndroid Build Coastguard Worker   }
645*6777b538SAndroid Build Coastguard Worker 
646*6777b538SAndroid Build Coastguard Worker   return file;
647*6777b538SAndroid Build Coastguard Worker }
648*6777b538SAndroid Build Coastguard Worker 
CreateTemporaryFileInDir(const FilePath & dir,FilePath * temp_file)649*6777b538SAndroid Build Coastguard Worker bool CreateTemporaryFileInDir(const FilePath& dir, FilePath* temp_file) {
650*6777b538SAndroid Build Coastguard Worker   return CreateAndOpenTemporaryFileInDir(dir, temp_file).IsValid();
651*6777b538SAndroid Build Coastguard Worker }
652*6777b538SAndroid Build Coastguard Worker 
FormatTemporaryFileName(FilePath::StringPieceType identifier)653*6777b538SAndroid Build Coastguard Worker FilePath FormatTemporaryFileName(FilePath::StringPieceType identifier) {
654*6777b538SAndroid Build Coastguard Worker   return FilePath(StrCat({identifier, FILE_PATH_LITERAL(".tmp")}));
655*6777b538SAndroid Build Coastguard Worker }
656*6777b538SAndroid Build Coastguard Worker 
CreateAndOpenTemporaryStreamInDir(const FilePath & dir,FilePath * path)657*6777b538SAndroid Build Coastguard Worker ScopedFILE CreateAndOpenTemporaryStreamInDir(const FilePath& dir,
658*6777b538SAndroid Build Coastguard Worker                                              FilePath* path) {
659*6777b538SAndroid Build Coastguard Worker   // Open file in binary mode, to avoid problems with fwrite. On Windows
660*6777b538SAndroid Build Coastguard Worker   // it replaces \n's with \r\n's, which may surprise you.
661*6777b538SAndroid Build Coastguard Worker   // Reference: http://msdn.microsoft.com/en-us/library/h9t88zwz(VS.71).aspx
662*6777b538SAndroid Build Coastguard Worker   return ScopedFILE(
663*6777b538SAndroid Build Coastguard Worker       FileToFILE(CreateAndOpenTemporaryFileInDir(dir, path), "wb+"));
664*6777b538SAndroid Build Coastguard Worker }
665*6777b538SAndroid Build Coastguard Worker 
CreateTemporaryDirInDir(const FilePath & base_dir,const FilePath::StringType & prefix,FilePath * new_dir)666*6777b538SAndroid Build Coastguard Worker bool CreateTemporaryDirInDir(const FilePath& base_dir,
667*6777b538SAndroid Build Coastguard Worker                              const FilePath::StringType& prefix,
668*6777b538SAndroid Build Coastguard Worker                              FilePath* new_dir) {
669*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
670*6777b538SAndroid Build Coastguard Worker 
671*6777b538SAndroid Build Coastguard Worker   FilePath path_to_create;
672*6777b538SAndroid Build Coastguard Worker 
673*6777b538SAndroid Build Coastguard Worker   for (int count = 0; count < 50; ++count) {
674*6777b538SAndroid Build Coastguard Worker     // Try create a new temporary directory with random generated name. If
675*6777b538SAndroid Build Coastguard Worker     // the one exists, keep trying another path name until we reach some limit.
676*6777b538SAndroid Build Coastguard Worker     std::wstring new_dir_name;
677*6777b538SAndroid Build Coastguard Worker     new_dir_name.assign(prefix);
678*6777b538SAndroid Build Coastguard Worker     new_dir_name.append(AsWString(NumberToString16(GetCurrentProcId())));
679*6777b538SAndroid Build Coastguard Worker     new_dir_name.push_back('_');
680*6777b538SAndroid Build Coastguard Worker     new_dir_name.append(AsWString(
681*6777b538SAndroid Build Coastguard Worker         NumberToString16(RandInt(0, std::numeric_limits<int32_t>::max()))));
682*6777b538SAndroid Build Coastguard Worker 
683*6777b538SAndroid Build Coastguard Worker     path_to_create = base_dir.Append(new_dir_name);
684*6777b538SAndroid Build Coastguard Worker     if (::CreateDirectory(path_to_create.value().c_str(), NULL)) {
685*6777b538SAndroid Build Coastguard Worker       *new_dir = path_to_create;
686*6777b538SAndroid Build Coastguard Worker       return true;
687*6777b538SAndroid Build Coastguard Worker     }
688*6777b538SAndroid Build Coastguard Worker   }
689*6777b538SAndroid Build Coastguard Worker 
690*6777b538SAndroid Build Coastguard Worker   return false;
691*6777b538SAndroid Build Coastguard Worker }
692*6777b538SAndroid Build Coastguard Worker 
GetSecureSystemTemp(FilePath * temp)693*6777b538SAndroid Build Coastguard Worker bool GetSecureSystemTemp(FilePath* temp) {
694*6777b538SAndroid Build Coastguard Worker   if (g_disable_secure_system_temp_for_testing) {
695*6777b538SAndroid Build Coastguard Worker     return false;
696*6777b538SAndroid Build Coastguard Worker   }
697*6777b538SAndroid Build Coastguard Worker 
698*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
699*6777b538SAndroid Build Coastguard Worker 
700*6777b538SAndroid Build Coastguard Worker   CHECK(temp);
701*6777b538SAndroid Build Coastguard Worker 
702*6777b538SAndroid Build Coastguard Worker   for (const auto key : {DIR_WINDOWS, DIR_PROGRAM_FILES}) {
703*6777b538SAndroid Build Coastguard Worker     FilePath secure_system_temp;
704*6777b538SAndroid Build Coastguard Worker     if (!PathService::Get(key, &secure_system_temp)) {
705*6777b538SAndroid Build Coastguard Worker       continue;
706*6777b538SAndroid Build Coastguard Worker     }
707*6777b538SAndroid Build Coastguard Worker 
708*6777b538SAndroid Build Coastguard Worker     if (key == DIR_WINDOWS) {
709*6777b538SAndroid Build Coastguard Worker       secure_system_temp = secure_system_temp.AppendASCII("SystemTemp");
710*6777b538SAndroid Build Coastguard Worker     }
711*6777b538SAndroid Build Coastguard Worker 
712*6777b538SAndroid Build Coastguard Worker     if (PathExists(secure_system_temp) && PathIsWritable(secure_system_temp)) {
713*6777b538SAndroid Build Coastguard Worker       *temp = secure_system_temp;
714*6777b538SAndroid Build Coastguard Worker       return true;
715*6777b538SAndroid Build Coastguard Worker     }
716*6777b538SAndroid Build Coastguard Worker   }
717*6777b538SAndroid Build Coastguard Worker 
718*6777b538SAndroid Build Coastguard Worker   return false;
719*6777b538SAndroid Build Coastguard Worker }
720*6777b538SAndroid Build Coastguard Worker 
SetDisableSecureSystemTempForTesting(bool disabled)721*6777b538SAndroid Build Coastguard Worker void SetDisableSecureSystemTempForTesting(bool disabled) {
722*6777b538SAndroid Build Coastguard Worker   g_disable_secure_system_temp_for_testing = disabled;
723*6777b538SAndroid Build Coastguard Worker }
724*6777b538SAndroid Build Coastguard Worker 
725*6777b538SAndroid Build Coastguard Worker // The directory is created under `GetSecureSystemTemp` for security reasons if
726*6777b538SAndroid Build Coastguard Worker // the caller is admin to avoid attacks from lower privilege processes.
727*6777b538SAndroid Build Coastguard Worker //
728*6777b538SAndroid Build Coastguard Worker // If unable to create a dir under `GetSecureSystemTemp`, the dir is created
729*6777b538SAndroid Build Coastguard Worker // under %TEMP%. The reasons for not being able to create a dir under
730*6777b538SAndroid Build Coastguard Worker // `GetSecureSystemTemp` could be because `%systemroot%\SystemTemp` does not
731*6777b538SAndroid Build Coastguard Worker // exist, or unable to resolve `DIR_WINDOWS` or `DIR_PROGRAM_FILES`, say due to
732*6777b538SAndroid Build Coastguard Worker // registry redirection, or unable to create a directory due to
733*6777b538SAndroid Build Coastguard Worker // `GetSecureSystemTemp` being read-only or having atypical ACLs. Tests can also
734*6777b538SAndroid Build Coastguard Worker // disable this behavior resulting in false being returned.
CreateNewTempDirectory(const FilePath::StringType & prefix,FilePath * new_temp_path)735*6777b538SAndroid Build Coastguard Worker bool CreateNewTempDirectory(const FilePath::StringType& prefix,
736*6777b538SAndroid Build Coastguard Worker                             FilePath* new_temp_path) {
737*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
738*6777b538SAndroid Build Coastguard Worker 
739*6777b538SAndroid Build Coastguard Worker   DCHECK(new_temp_path);
740*6777b538SAndroid Build Coastguard Worker 
741*6777b538SAndroid Build Coastguard Worker   FilePath parent_dir;
742*6777b538SAndroid Build Coastguard Worker   if (::IsUserAnAdmin() && GetSecureSystemTemp(&parent_dir) &&
743*6777b538SAndroid Build Coastguard Worker       CreateTemporaryDirInDir(parent_dir,
744*6777b538SAndroid Build Coastguard Worker                               prefix.empty() ? kDefaultTempDirPrefix : prefix,
745*6777b538SAndroid Build Coastguard Worker                               new_temp_path)) {
746*6777b538SAndroid Build Coastguard Worker     return true;
747*6777b538SAndroid Build Coastguard Worker   }
748*6777b538SAndroid Build Coastguard Worker 
749*6777b538SAndroid Build Coastguard Worker   if (!GetTempDir(&parent_dir))
750*6777b538SAndroid Build Coastguard Worker     return false;
751*6777b538SAndroid Build Coastguard Worker 
752*6777b538SAndroid Build Coastguard Worker   return CreateTemporaryDirInDir(parent_dir, prefix, new_temp_path);
753*6777b538SAndroid Build Coastguard Worker }
754*6777b538SAndroid Build Coastguard Worker 
CreateDirectoryAndGetError(const FilePath & full_path,File::Error * error)755*6777b538SAndroid Build Coastguard Worker bool CreateDirectoryAndGetError(const FilePath& full_path,
756*6777b538SAndroid Build Coastguard Worker                                 File::Error* error) {
757*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
758*6777b538SAndroid Build Coastguard Worker 
759*6777b538SAndroid Build Coastguard Worker   // If the path exists, we've succeeded if it's a directory, failed otherwise.
760*6777b538SAndroid Build Coastguard Worker   const wchar_t* const full_path_str = full_path.value().c_str();
761*6777b538SAndroid Build Coastguard Worker   const DWORD fileattr = ::GetFileAttributes(full_path_str);
762*6777b538SAndroid Build Coastguard Worker   if (fileattr != INVALID_FILE_ATTRIBUTES) {
763*6777b538SAndroid Build Coastguard Worker     if ((fileattr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
764*6777b538SAndroid Build Coastguard Worker       return true;
765*6777b538SAndroid Build Coastguard Worker     }
766*6777b538SAndroid Build Coastguard Worker     DLOG(WARNING) << "CreateDirectory(" << full_path_str << "), "
767*6777b538SAndroid Build Coastguard Worker                   << "conflicts with existing file.";
768*6777b538SAndroid Build Coastguard Worker     if (error)
769*6777b538SAndroid Build Coastguard Worker       *error = File::FILE_ERROR_NOT_A_DIRECTORY;
770*6777b538SAndroid Build Coastguard Worker     ::SetLastError(ERROR_FILE_EXISTS);
771*6777b538SAndroid Build Coastguard Worker     return false;
772*6777b538SAndroid Build Coastguard Worker   }
773*6777b538SAndroid Build Coastguard Worker 
774*6777b538SAndroid Build Coastguard Worker   // Invariant:  Path does not exist as file or directory.
775*6777b538SAndroid Build Coastguard Worker 
776*6777b538SAndroid Build Coastguard Worker   // Attempt to create the parent recursively.  This will immediately return
777*6777b538SAndroid Build Coastguard Worker   // true if it already exists, otherwise will create all required parent
778*6777b538SAndroid Build Coastguard Worker   // directories starting with the highest-level missing parent.
779*6777b538SAndroid Build Coastguard Worker   FilePath parent_path(full_path.DirName());
780*6777b538SAndroid Build Coastguard Worker   if (parent_path.value() == full_path.value()) {
781*6777b538SAndroid Build Coastguard Worker     if (error)
782*6777b538SAndroid Build Coastguard Worker       *error = File::FILE_ERROR_NOT_FOUND;
783*6777b538SAndroid Build Coastguard Worker     ::SetLastError(ERROR_FILE_NOT_FOUND);
784*6777b538SAndroid Build Coastguard Worker     return false;
785*6777b538SAndroid Build Coastguard Worker   }
786*6777b538SAndroid Build Coastguard Worker   if (!CreateDirectoryAndGetError(parent_path, error)) {
787*6777b538SAndroid Build Coastguard Worker     DLOG(WARNING) << "Failed to create one of the parent directories.";
788*6777b538SAndroid Build Coastguard Worker     DCHECK(!error || *error != File::FILE_OK);
789*6777b538SAndroid Build Coastguard Worker     return false;
790*6777b538SAndroid Build Coastguard Worker   }
791*6777b538SAndroid Build Coastguard Worker 
792*6777b538SAndroid Build Coastguard Worker   if (::CreateDirectory(full_path_str, NULL))
793*6777b538SAndroid Build Coastguard Worker     return true;
794*6777b538SAndroid Build Coastguard Worker 
795*6777b538SAndroid Build Coastguard Worker   const DWORD error_code = ::GetLastError();
796*6777b538SAndroid Build Coastguard Worker   if (error_code == ERROR_ALREADY_EXISTS && DirectoryExists(full_path)) {
797*6777b538SAndroid Build Coastguard Worker     // This error code ERROR_ALREADY_EXISTS doesn't indicate whether we were
798*6777b538SAndroid Build Coastguard Worker     // racing with someone creating the same directory, or a file with the same
799*6777b538SAndroid Build Coastguard Worker     // path.  If DirectoryExists() returns true, we lost the race to create the
800*6777b538SAndroid Build Coastguard Worker     // same directory.
801*6777b538SAndroid Build Coastguard Worker     return true;
802*6777b538SAndroid Build Coastguard Worker   }
803*6777b538SAndroid Build Coastguard Worker   if (error)
804*6777b538SAndroid Build Coastguard Worker     *error = File::OSErrorToFileError(error_code);
805*6777b538SAndroid Build Coastguard Worker   ::SetLastError(error_code);
806*6777b538SAndroid Build Coastguard Worker   DPLOG(WARNING) << "Failed to create directory " << full_path_str;
807*6777b538SAndroid Build Coastguard Worker   return false;
808*6777b538SAndroid Build Coastguard Worker }
809*6777b538SAndroid Build Coastguard Worker 
NormalizeFilePath(const FilePath & path,FilePath * real_path)810*6777b538SAndroid Build Coastguard Worker bool NormalizeFilePath(const FilePath& path, FilePath* real_path) {
811*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
812*6777b538SAndroid Build Coastguard Worker   File file(path,
813*6777b538SAndroid Build Coastguard Worker             File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WIN_SHARE_DELETE);
814*6777b538SAndroid Build Coastguard Worker   if (!file.IsValid())
815*6777b538SAndroid Build Coastguard Worker     return false;
816*6777b538SAndroid Build Coastguard Worker 
817*6777b538SAndroid Build Coastguard Worker   // The expansion of |path| into a full path may make it longer.
818*6777b538SAndroid Build Coastguard Worker   constexpr int kMaxPathLength = MAX_PATH + 10;
819*6777b538SAndroid Build Coastguard Worker   wchar_t native_file_path[kMaxPathLength];
820*6777b538SAndroid Build Coastguard Worker   // On success, `used_wchars` returns the number of written characters, not
821*6777b538SAndroid Build Coastguard Worker   // include the trailing '\0'. Thus, failure is indicated by returning 0 or >=
822*6777b538SAndroid Build Coastguard Worker   // kMaxPathLength.
823*6777b538SAndroid Build Coastguard Worker   DWORD used_wchars = ::GetFinalPathNameByHandle(
824*6777b538SAndroid Build Coastguard Worker       file.GetPlatformFile(), native_file_path, kMaxPathLength,
825*6777b538SAndroid Build Coastguard Worker       FILE_NAME_NORMALIZED | VOLUME_NAME_NT);
826*6777b538SAndroid Build Coastguard Worker 
827*6777b538SAndroid Build Coastguard Worker   if (used_wchars >= kMaxPathLength || used_wchars == 0)
828*6777b538SAndroid Build Coastguard Worker     return false;
829*6777b538SAndroid Build Coastguard Worker 
830*6777b538SAndroid Build Coastguard Worker   // GetFinalPathNameByHandle() returns the \\?\ syntax for file names and
831*6777b538SAndroid Build Coastguard Worker   // existing code expects we return a path starting 'X:\' so we call
832*6777b538SAndroid Build Coastguard Worker   // DevicePathToDriveLetterPath rather than using VOLUME_NAME_DOS above.
833*6777b538SAndroid Build Coastguard Worker   return DevicePathToDriveLetterPath(
834*6777b538SAndroid Build Coastguard Worker       FilePath(FilePath::StringPieceType(native_file_path, used_wchars)),
835*6777b538SAndroid Build Coastguard Worker       real_path);
836*6777b538SAndroid Build Coastguard Worker }
837*6777b538SAndroid Build Coastguard Worker 
DevicePathToDriveLetterPath(const FilePath & nt_device_path,FilePath * out_drive_letter_path)838*6777b538SAndroid Build Coastguard Worker bool DevicePathToDriveLetterPath(const FilePath& nt_device_path,
839*6777b538SAndroid Build Coastguard Worker                                  FilePath* out_drive_letter_path) {
840*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
841*6777b538SAndroid Build Coastguard Worker 
842*6777b538SAndroid Build Coastguard Worker   // Get the mapping of drive letters to device paths.
843*6777b538SAndroid Build Coastguard Worker   const int kDriveMappingSize = 1024;
844*6777b538SAndroid Build Coastguard Worker   wchar_t drive_mapping[kDriveMappingSize] = {'\0'};
845*6777b538SAndroid Build Coastguard Worker   if (!::GetLogicalDriveStrings(kDriveMappingSize - 1, drive_mapping)) {
846*6777b538SAndroid Build Coastguard Worker     DLOG(ERROR) << "Failed to get drive mapping.";
847*6777b538SAndroid Build Coastguard Worker     return false;
848*6777b538SAndroid Build Coastguard Worker   }
849*6777b538SAndroid Build Coastguard Worker 
850*6777b538SAndroid Build Coastguard Worker   // The drive mapping is a sequence of null terminated strings.
851*6777b538SAndroid Build Coastguard Worker   // The last string is empty.
852*6777b538SAndroid Build Coastguard Worker   wchar_t* drive_map_ptr = drive_mapping;
853*6777b538SAndroid Build Coastguard Worker   wchar_t device_path_as_string[MAX_PATH];
854*6777b538SAndroid Build Coastguard Worker   wchar_t drive[] = FILE_PATH_LITERAL(" :");
855*6777b538SAndroid Build Coastguard Worker 
856*6777b538SAndroid Build Coastguard Worker   // For each string in the drive mapping, get the junction that links
857*6777b538SAndroid Build Coastguard Worker   // to it.  If that junction is a prefix of |device_path|, then we
858*6777b538SAndroid Build Coastguard Worker   // know that |drive| is the real path prefix.
859*6777b538SAndroid Build Coastguard Worker   while (*drive_map_ptr) {
860*6777b538SAndroid Build Coastguard Worker     drive[0] = drive_map_ptr[0];  // Copy the drive letter.
861*6777b538SAndroid Build Coastguard Worker 
862*6777b538SAndroid Build Coastguard Worker     if (QueryDosDevice(drive, device_path_as_string, MAX_PATH)) {
863*6777b538SAndroid Build Coastguard Worker       FilePath device_path(device_path_as_string);
864*6777b538SAndroid Build Coastguard Worker       if (device_path == nt_device_path ||
865*6777b538SAndroid Build Coastguard Worker           device_path.IsParent(nt_device_path)) {
866*6777b538SAndroid Build Coastguard Worker         *out_drive_letter_path =
867*6777b538SAndroid Build Coastguard Worker             FilePath(drive + nt_device_path.value().substr(
868*6777b538SAndroid Build Coastguard Worker                                  wcslen(device_path_as_string)));
869*6777b538SAndroid Build Coastguard Worker         return true;
870*6777b538SAndroid Build Coastguard Worker       }
871*6777b538SAndroid Build Coastguard Worker     }
872*6777b538SAndroid Build Coastguard Worker     // Move to the next drive letter string, which starts one
873*6777b538SAndroid Build Coastguard Worker     // increment after the '\0' that terminates the current string.
874*6777b538SAndroid Build Coastguard Worker     while (*drive_map_ptr++) {}
875*6777b538SAndroid Build Coastguard Worker   }
876*6777b538SAndroid Build Coastguard Worker 
877*6777b538SAndroid Build Coastguard Worker   // No drive matched.  The path does not start with a device junction
878*6777b538SAndroid Build Coastguard Worker   // that is mounted as a drive letter.  This means there is no drive
879*6777b538SAndroid Build Coastguard Worker   // letter path to the volume that holds |device_path|, so fail.
880*6777b538SAndroid Build Coastguard Worker   return false;
881*6777b538SAndroid Build Coastguard Worker }
882*6777b538SAndroid Build Coastguard Worker 
MakeLongFilePath(const FilePath & input)883*6777b538SAndroid Build Coastguard Worker FilePath MakeLongFilePath(const FilePath& input) {
884*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
885*6777b538SAndroid Build Coastguard Worker 
886*6777b538SAndroid Build Coastguard Worker   DWORD path_long_len = ::GetLongPathName(input.value().c_str(), nullptr, 0);
887*6777b538SAndroid Build Coastguard Worker   if (path_long_len == 0UL)
888*6777b538SAndroid Build Coastguard Worker     return FilePath();
889*6777b538SAndroid Build Coastguard Worker 
890*6777b538SAndroid Build Coastguard Worker   std::wstring path_long_str;
891*6777b538SAndroid Build Coastguard Worker   path_long_len = ::GetLongPathName(input.value().c_str(),
892*6777b538SAndroid Build Coastguard Worker                                     WriteInto(&path_long_str, path_long_len),
893*6777b538SAndroid Build Coastguard Worker                                     path_long_len);
894*6777b538SAndroid Build Coastguard Worker   if (path_long_len == 0UL)
895*6777b538SAndroid Build Coastguard Worker     return FilePath();
896*6777b538SAndroid Build Coastguard Worker 
897*6777b538SAndroid Build Coastguard Worker   return FilePath(path_long_str);
898*6777b538SAndroid Build Coastguard Worker }
899*6777b538SAndroid Build Coastguard Worker 
CreateWinHardLink(const FilePath & to_file,const FilePath & from_file)900*6777b538SAndroid Build Coastguard Worker bool CreateWinHardLink(const FilePath& to_file, const FilePath& from_file) {
901*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
902*6777b538SAndroid Build Coastguard Worker   return ::CreateHardLink(to_file.value().c_str(), from_file.value().c_str(),
903*6777b538SAndroid Build Coastguard Worker                           nullptr);
904*6777b538SAndroid Build Coastguard Worker }
905*6777b538SAndroid Build Coastguard Worker 
IsLink(const FilePath & file_path)906*6777b538SAndroid Build Coastguard Worker bool IsLink(const FilePath& file_path) {
907*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
908*6777b538SAndroid Build Coastguard Worker 
909*6777b538SAndroid Build Coastguard Worker   // Opens the file or directory specified by file_path for querying attributes.
910*6777b538SAndroid Build Coastguard Worker   // No access rights are requested (FILE_READ_ATTRIBUTES), as we're only
911*6777b538SAndroid Build Coastguard Worker   // interested in the attributes. The file share mode allows other processes to
912*6777b538SAndroid Build Coastguard Worker   // read, write, and delete the file while we have it open. The flags
913*6777b538SAndroid Build Coastguard Worker   // FILE_FLAG_BACKUP_SEMANTICS and FILE_FLAG_OPEN_REPARSE_POINT are used to
914*6777b538SAndroid Build Coastguard Worker   // ensure we can open directories and work with reparse points, respectively.
915*6777b538SAndroid Build Coastguard Worker   //
916*6777b538SAndroid Build Coastguard Worker   // NOTE: In future, we can consider using GetFileInformationByName(...)
917*6777b538SAndroid Build Coastguard Worker   // instead.
918*6777b538SAndroid Build Coastguard Worker   win::ScopedHandle file(
919*6777b538SAndroid Build Coastguard Worker       ::CreateFile(file_path.value().c_str(), FILE_READ_ATTRIBUTES,
920*6777b538SAndroid Build Coastguard Worker                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
921*6777b538SAndroid Build Coastguard Worker                    /*lpSecurityAttributes=*/nullptr, OPEN_EXISTING,
922*6777b538SAndroid Build Coastguard Worker                    FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
923*6777b538SAndroid Build Coastguard Worker                    /*hTemplateFile=*/nullptr));
924*6777b538SAndroid Build Coastguard Worker 
925*6777b538SAndroid Build Coastguard Worker   if (!file.is_valid()) {
926*6777b538SAndroid Build Coastguard Worker     return false;
927*6777b538SAndroid Build Coastguard Worker   }
928*6777b538SAndroid Build Coastguard Worker 
929*6777b538SAndroid Build Coastguard Worker   FILE_ATTRIBUTE_TAG_INFO attr_taginfo;
930*6777b538SAndroid Build Coastguard Worker   if (!::GetFileInformationByHandleEx(file.get(), FileAttributeTagInfo,
931*6777b538SAndroid Build Coastguard Worker                                       &attr_taginfo, sizeof(attr_taginfo))) {
932*6777b538SAndroid Build Coastguard Worker     return false;
933*6777b538SAndroid Build Coastguard Worker   }
934*6777b538SAndroid Build Coastguard Worker 
935*6777b538SAndroid Build Coastguard Worker   return (attr_taginfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
936*6777b538SAndroid Build Coastguard Worker          (attr_taginfo.ReparseTag == IO_REPARSE_TAG_SYMLINK);
937*6777b538SAndroid Build Coastguard Worker }
938*6777b538SAndroid Build Coastguard Worker 
GetFileInfo(const FilePath & file_path,File::Info * results)939*6777b538SAndroid Build Coastguard Worker bool GetFileInfo(const FilePath& file_path, File::Info* results) {
940*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
941*6777b538SAndroid Build Coastguard Worker 
942*6777b538SAndroid Build Coastguard Worker   WIN32_FILE_ATTRIBUTE_DATA attr;
943*6777b538SAndroid Build Coastguard Worker   if (!GetFileAttributesEx(file_path.value().c_str(), GetFileExInfoStandard,
944*6777b538SAndroid Build Coastguard Worker                            &attr)) {
945*6777b538SAndroid Build Coastguard Worker     return false;
946*6777b538SAndroid Build Coastguard Worker   }
947*6777b538SAndroid Build Coastguard Worker 
948*6777b538SAndroid Build Coastguard Worker   ULARGE_INTEGER size;
949*6777b538SAndroid Build Coastguard Worker   size.HighPart = attr.nFileSizeHigh;
950*6777b538SAndroid Build Coastguard Worker   size.LowPart = attr.nFileSizeLow;
951*6777b538SAndroid Build Coastguard Worker   // TODO(crbug.com/1333521): Change Info::size to uint64_t and eliminate this
952*6777b538SAndroid Build Coastguard Worker   // cast.
953*6777b538SAndroid Build Coastguard Worker   results->size = checked_cast<int64_t>(size.QuadPart);
954*6777b538SAndroid Build Coastguard Worker 
955*6777b538SAndroid Build Coastguard Worker   results->is_directory =
956*6777b538SAndroid Build Coastguard Worker       (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
957*6777b538SAndroid Build Coastguard Worker   results->last_modified = Time::FromFileTime(attr.ftLastWriteTime);
958*6777b538SAndroid Build Coastguard Worker   results->last_accessed = Time::FromFileTime(attr.ftLastAccessTime);
959*6777b538SAndroid Build Coastguard Worker   results->creation_time = Time::FromFileTime(attr.ftCreationTime);
960*6777b538SAndroid Build Coastguard Worker 
961*6777b538SAndroid Build Coastguard Worker   return true;
962*6777b538SAndroid Build Coastguard Worker }
963*6777b538SAndroid Build Coastguard Worker 
OpenFile(const FilePath & filename,const char * mode)964*6777b538SAndroid Build Coastguard Worker FILE* OpenFile(const FilePath& filename, const char* mode) {
965*6777b538SAndroid Build Coastguard Worker   // 'N' is unconditionally added below, so be sure there is not one already
966*6777b538SAndroid Build Coastguard Worker   // present before a comma in |mode|.
967*6777b538SAndroid Build Coastguard Worker   DCHECK(
968*6777b538SAndroid Build Coastguard Worker       strchr(mode, 'N') == nullptr ||
969*6777b538SAndroid Build Coastguard Worker       (strchr(mode, ',') != nullptr && strchr(mode, 'N') > strchr(mode, ',')));
970*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
971*6777b538SAndroid Build Coastguard Worker   std::wstring w_mode = UTF8ToWide(mode);
972*6777b538SAndroid Build Coastguard Worker   AppendModeCharacter(L'N', &w_mode);
973*6777b538SAndroid Build Coastguard Worker   return _wfsopen(filename.value().c_str(), w_mode.c_str(), _SH_DENYNO);
974*6777b538SAndroid Build Coastguard Worker }
975*6777b538SAndroid Build Coastguard Worker 
FileToFILE(File file,const char * mode)976*6777b538SAndroid Build Coastguard Worker FILE* FileToFILE(File file, const char* mode) {
977*6777b538SAndroid Build Coastguard Worker   DCHECK(!file.async());
978*6777b538SAndroid Build Coastguard Worker   if (!file.IsValid())
979*6777b538SAndroid Build Coastguard Worker     return NULL;
980*6777b538SAndroid Build Coastguard Worker   int fd =
981*6777b538SAndroid Build Coastguard Worker       _open_osfhandle(reinterpret_cast<intptr_t>(file.GetPlatformFile()), 0);
982*6777b538SAndroid Build Coastguard Worker   if (fd < 0)
983*6777b538SAndroid Build Coastguard Worker     return NULL;
984*6777b538SAndroid Build Coastguard Worker   file.TakePlatformFile();
985*6777b538SAndroid Build Coastguard Worker   FILE* stream = _fdopen(fd, mode);
986*6777b538SAndroid Build Coastguard Worker   if (!stream)
987*6777b538SAndroid Build Coastguard Worker     _close(fd);
988*6777b538SAndroid Build Coastguard Worker   return stream;
989*6777b538SAndroid Build Coastguard Worker }
990*6777b538SAndroid Build Coastguard Worker 
FILEToFile(FILE * file_stream)991*6777b538SAndroid Build Coastguard Worker File FILEToFile(FILE* file_stream) {
992*6777b538SAndroid Build Coastguard Worker   if (!file_stream)
993*6777b538SAndroid Build Coastguard Worker     return File();
994*6777b538SAndroid Build Coastguard Worker 
995*6777b538SAndroid Build Coastguard Worker   int fd = _fileno(file_stream);
996*6777b538SAndroid Build Coastguard Worker   DCHECK_GE(fd, 0);
997*6777b538SAndroid Build Coastguard Worker   intptr_t file_handle = _get_osfhandle(fd);
998*6777b538SAndroid Build Coastguard Worker   DCHECK_NE(file_handle, reinterpret_cast<intptr_t>(INVALID_HANDLE_VALUE));
999*6777b538SAndroid Build Coastguard Worker 
1000*6777b538SAndroid Build Coastguard Worker   HANDLE other_handle = nullptr;
1001*6777b538SAndroid Build Coastguard Worker   if (!::DuplicateHandle(
1002*6777b538SAndroid Build Coastguard Worker           /*hSourceProcessHandle=*/GetCurrentProcess(),
1003*6777b538SAndroid Build Coastguard Worker           reinterpret_cast<HANDLE>(file_handle),
1004*6777b538SAndroid Build Coastguard Worker           /*hTargetProcessHandle=*/GetCurrentProcess(), &other_handle,
1005*6777b538SAndroid Build Coastguard Worker           /*dwDesiredAccess=*/0,
1006*6777b538SAndroid Build Coastguard Worker           /*bInheritHandle=*/FALSE,
1007*6777b538SAndroid Build Coastguard Worker           /*dwOptions=*/DUPLICATE_SAME_ACCESS)) {
1008*6777b538SAndroid Build Coastguard Worker     return File(File::GetLastFileError());
1009*6777b538SAndroid Build Coastguard Worker   }
1010*6777b538SAndroid Build Coastguard Worker 
1011*6777b538SAndroid Build Coastguard Worker   return File(ScopedPlatformFile(other_handle));
1012*6777b538SAndroid Build Coastguard Worker }
1013*6777b538SAndroid Build Coastguard Worker 
ReadFile(const FilePath & filename,span<char> buffer)1014*6777b538SAndroid Build Coastguard Worker std::optional<uint64_t> ReadFile(const FilePath& filename, span<char> buffer) {
1015*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
1016*6777b538SAndroid Build Coastguard Worker   win::ScopedHandle file(CreateFile(filename.value().c_str(), GENERIC_READ,
1017*6777b538SAndroid Build Coastguard Worker                                     FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1018*6777b538SAndroid Build Coastguard Worker                                     OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN,
1019*6777b538SAndroid Build Coastguard Worker                                     NULL));
1020*6777b538SAndroid Build Coastguard Worker   if (!file.is_valid()) {
1021*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
1022*6777b538SAndroid Build Coastguard Worker   }
1023*6777b538SAndroid Build Coastguard Worker 
1024*6777b538SAndroid Build Coastguard Worker   // TODO(crbug.com/1333521): Consider supporting reading more than INT_MAX
1025*6777b538SAndroid Build Coastguard Worker   // bytes.
1026*6777b538SAndroid Build Coastguard Worker   DWORD bytes_to_read = static_cast<DWORD>(checked_cast<int>(buffer.size()));
1027*6777b538SAndroid Build Coastguard Worker 
1028*6777b538SAndroid Build Coastguard Worker   DWORD bytes_read;
1029*6777b538SAndroid Build Coastguard Worker   if (!::ReadFile(file.get(), buffer.data(), bytes_to_read, &bytes_read,
1030*6777b538SAndroid Build Coastguard Worker                   nullptr)) {
1031*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
1032*6777b538SAndroid Build Coastguard Worker   }
1033*6777b538SAndroid Build Coastguard Worker   return bytes_read;
1034*6777b538SAndroid Build Coastguard Worker }
1035*6777b538SAndroid Build Coastguard Worker 
WriteFile(const FilePath & filename,const char * data,int size)1036*6777b538SAndroid Build Coastguard Worker int WriteFile(const FilePath& filename, const char* data, int size) {
1037*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
1038*6777b538SAndroid Build Coastguard Worker   win::ScopedHandle file(CreateFile(filename.value().c_str(), GENERIC_WRITE, 0,
1039*6777b538SAndroid Build Coastguard Worker                                     NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
1040*6777b538SAndroid Build Coastguard Worker                                     NULL));
1041*6777b538SAndroid Build Coastguard Worker   if (!file.is_valid() || size < 0) {
1042*6777b538SAndroid Build Coastguard Worker     DPLOG(WARNING) << "WriteFile failed for path " << filename.value();
1043*6777b538SAndroid Build Coastguard Worker     return -1;
1044*6777b538SAndroid Build Coastguard Worker   }
1045*6777b538SAndroid Build Coastguard Worker 
1046*6777b538SAndroid Build Coastguard Worker   DWORD written;
1047*6777b538SAndroid Build Coastguard Worker   BOOL result =
1048*6777b538SAndroid Build Coastguard Worker       ::WriteFile(file.get(), data, static_cast<DWORD>(size), &written, NULL);
1049*6777b538SAndroid Build Coastguard Worker   if (result && static_cast<int>(written) == size)
1050*6777b538SAndroid Build Coastguard Worker     return static_cast<int>(written);
1051*6777b538SAndroid Build Coastguard Worker 
1052*6777b538SAndroid Build Coastguard Worker   if (!result) {
1053*6777b538SAndroid Build Coastguard Worker     // WriteFile failed.
1054*6777b538SAndroid Build Coastguard Worker     DPLOG(WARNING) << "writing file " << filename.value() << " failed";
1055*6777b538SAndroid Build Coastguard Worker   } else {
1056*6777b538SAndroid Build Coastguard Worker     // Didn't write all the bytes.
1057*6777b538SAndroid Build Coastguard Worker     DLOG(WARNING) << "wrote" << written << " bytes to " << filename.value()
1058*6777b538SAndroid Build Coastguard Worker                   << " expected " << size;
1059*6777b538SAndroid Build Coastguard Worker   }
1060*6777b538SAndroid Build Coastguard Worker   return -1;
1061*6777b538SAndroid Build Coastguard Worker }
1062*6777b538SAndroid Build Coastguard Worker 
AppendToFile(const FilePath & filename,span<const uint8_t> data)1063*6777b538SAndroid Build Coastguard Worker bool AppendToFile(const FilePath& filename, span<const uint8_t> data) {
1064*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
1065*6777b538SAndroid Build Coastguard Worker   win::ScopedHandle file(CreateFile(filename.value().c_str(), FILE_APPEND_DATA,
1066*6777b538SAndroid Build Coastguard Worker                                     0, nullptr, OPEN_EXISTING, 0, nullptr));
1067*6777b538SAndroid Build Coastguard Worker   if (!file.is_valid()) {
1068*6777b538SAndroid Build Coastguard Worker     VPLOG(1) << "CreateFile failed for path " << filename.value();
1069*6777b538SAndroid Build Coastguard Worker     return false;
1070*6777b538SAndroid Build Coastguard Worker   }
1071*6777b538SAndroid Build Coastguard Worker 
1072*6777b538SAndroid Build Coastguard Worker   DWORD written;
1073*6777b538SAndroid Build Coastguard Worker   DWORD size = checked_cast<DWORD>(data.size());
1074*6777b538SAndroid Build Coastguard Worker   BOOL result = ::WriteFile(file.get(), data.data(), size, &written, nullptr);
1075*6777b538SAndroid Build Coastguard Worker   if (result && written == size)
1076*6777b538SAndroid Build Coastguard Worker     return true;
1077*6777b538SAndroid Build Coastguard Worker 
1078*6777b538SAndroid Build Coastguard Worker   if (!result) {
1079*6777b538SAndroid Build Coastguard Worker     // WriteFile failed.
1080*6777b538SAndroid Build Coastguard Worker     VPLOG(1) << "Writing file " << filename.value() << " failed";
1081*6777b538SAndroid Build Coastguard Worker   } else {
1082*6777b538SAndroid Build Coastguard Worker     // Didn't write all the bytes.
1083*6777b538SAndroid Build Coastguard Worker     VPLOG(1) << "Only wrote " << written << " out of " << size << " byte(s) to "
1084*6777b538SAndroid Build Coastguard Worker              << filename.value();
1085*6777b538SAndroid Build Coastguard Worker   }
1086*6777b538SAndroid Build Coastguard Worker   return false;
1087*6777b538SAndroid Build Coastguard Worker }
1088*6777b538SAndroid Build Coastguard Worker 
AppendToFile(const FilePath & filename,StringPiece data)1089*6777b538SAndroid Build Coastguard Worker bool AppendToFile(const FilePath& filename, StringPiece data) {
1090*6777b538SAndroid Build Coastguard Worker   return AppendToFile(filename, as_bytes(make_span(data)));
1091*6777b538SAndroid Build Coastguard Worker }
1092*6777b538SAndroid Build Coastguard Worker 
GetCurrentDirectory(FilePath * dir)1093*6777b538SAndroid Build Coastguard Worker bool GetCurrentDirectory(FilePath* dir) {
1094*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
1095*6777b538SAndroid Build Coastguard Worker 
1096*6777b538SAndroid Build Coastguard Worker   wchar_t system_buffer[MAX_PATH];
1097*6777b538SAndroid Build Coastguard Worker   system_buffer[0] = 0;
1098*6777b538SAndroid Build Coastguard Worker   DWORD len = ::GetCurrentDirectory(MAX_PATH, system_buffer);
1099*6777b538SAndroid Build Coastguard Worker   if (len == 0 || len > MAX_PATH)
1100*6777b538SAndroid Build Coastguard Worker     return false;
1101*6777b538SAndroid Build Coastguard Worker   // TODO(evanm): the old behavior of this function was to always strip the
1102*6777b538SAndroid Build Coastguard Worker   // trailing slash.  We duplicate this here, but it shouldn't be necessary
1103*6777b538SAndroid Build Coastguard Worker   // when everyone is using the appropriate FilePath APIs.
1104*6777b538SAndroid Build Coastguard Worker   *dir = FilePath(FilePath::StringPieceType(system_buffer))
1105*6777b538SAndroid Build Coastguard Worker              .StripTrailingSeparators();
1106*6777b538SAndroid Build Coastguard Worker   return true;
1107*6777b538SAndroid Build Coastguard Worker }
1108*6777b538SAndroid Build Coastguard Worker 
SetCurrentDirectory(const FilePath & directory)1109*6777b538SAndroid Build Coastguard Worker bool SetCurrentDirectory(const FilePath& directory) {
1110*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
1111*6777b538SAndroid Build Coastguard Worker   return ::SetCurrentDirectory(directory.value().c_str()) != 0;
1112*6777b538SAndroid Build Coastguard Worker }
1113*6777b538SAndroid Build Coastguard Worker 
GetMaximumPathComponentLength(const FilePath & path)1114*6777b538SAndroid Build Coastguard Worker int GetMaximumPathComponentLength(const FilePath& path) {
1115*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
1116*6777b538SAndroid Build Coastguard Worker 
1117*6777b538SAndroid Build Coastguard Worker   wchar_t volume_path[MAX_PATH];
1118*6777b538SAndroid Build Coastguard Worker   if (!GetVolumePathNameW(path.NormalizePathSeparators().value().c_str(),
1119*6777b538SAndroid Build Coastguard Worker                           volume_path, std::size(volume_path))) {
1120*6777b538SAndroid Build Coastguard Worker     return -1;
1121*6777b538SAndroid Build Coastguard Worker   }
1122*6777b538SAndroid Build Coastguard Worker 
1123*6777b538SAndroid Build Coastguard Worker   DWORD max_length = 0;
1124*6777b538SAndroid Build Coastguard Worker   if (!GetVolumeInformationW(volume_path, NULL, 0, NULL, &max_length, NULL,
1125*6777b538SAndroid Build Coastguard Worker                              NULL, 0)) {
1126*6777b538SAndroid Build Coastguard Worker     return -1;
1127*6777b538SAndroid Build Coastguard Worker   }
1128*6777b538SAndroid Build Coastguard Worker 
1129*6777b538SAndroid Build Coastguard Worker   // Length of |path| with path separator appended.
1130*6777b538SAndroid Build Coastguard Worker   size_t prefix = path.StripTrailingSeparators().value().size() + 1;
1131*6777b538SAndroid Build Coastguard Worker   // The whole path string must be shorter than MAX_PATH. That is, it must be
1132*6777b538SAndroid Build Coastguard Worker   // prefix + component_length < MAX_PATH (or equivalently, <= MAX_PATH - 1).
1133*6777b538SAndroid Build Coastguard Worker   int whole_path_limit = std::max(0, MAX_PATH - 1 - static_cast<int>(prefix));
1134*6777b538SAndroid Build Coastguard Worker   return std::min(whole_path_limit, static_cast<int>(max_length));
1135*6777b538SAndroid Build Coastguard Worker }
1136*6777b538SAndroid Build Coastguard Worker 
CopyFile(const FilePath & from_path,const FilePath & to_path)1137*6777b538SAndroid Build Coastguard Worker bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
1138*6777b538SAndroid Build Coastguard Worker   return DoCopyFile(from_path, to_path, false);
1139*6777b538SAndroid Build Coastguard Worker }
1140*6777b538SAndroid Build Coastguard Worker 
SetNonBlocking(int fd)1141*6777b538SAndroid Build Coastguard Worker bool SetNonBlocking(int fd) {
1142*6777b538SAndroid Build Coastguard Worker   unsigned long nonblocking = 1;
1143*6777b538SAndroid Build Coastguard Worker   if (ioctlsocket(static_cast<SOCKET>(fd), static_cast<long>(FIONBIO),
1144*6777b538SAndroid Build Coastguard Worker                   &nonblocking) == 0)
1145*6777b538SAndroid Build Coastguard Worker     return true;
1146*6777b538SAndroid Build Coastguard Worker   return false;
1147*6777b538SAndroid Build Coastguard Worker }
1148*6777b538SAndroid Build Coastguard Worker 
PreReadFile(const FilePath & file_path,bool is_executable,bool sequential,int64_t max_bytes)1149*6777b538SAndroid Build Coastguard Worker bool PreReadFile(const FilePath& file_path,
1150*6777b538SAndroid Build Coastguard Worker                  bool is_executable,
1151*6777b538SAndroid Build Coastguard Worker                  bool sequential,
1152*6777b538SAndroid Build Coastguard Worker                  int64_t max_bytes) {
1153*6777b538SAndroid Build Coastguard Worker   DCHECK_GE(max_bytes, 0);
1154*6777b538SAndroid Build Coastguard Worker 
1155*6777b538SAndroid Build Coastguard Worker   if (max_bytes == 0) {
1156*6777b538SAndroid Build Coastguard Worker     // ::PrefetchVirtualMemory() fails when asked to read zero bytes.
1157*6777b538SAndroid Build Coastguard Worker     // base::MemoryMappedFile::Initialize() fails on an empty file.
1158*6777b538SAndroid Build Coastguard Worker     return true;
1159*6777b538SAndroid Build Coastguard Worker   }
1160*6777b538SAndroid Build Coastguard Worker 
1161*6777b538SAndroid Build Coastguard Worker   // ::PrefetchVirtualMemory() fails if the file is opened with write access.
1162*6777b538SAndroid Build Coastguard Worker   MemoryMappedFile::Access access = is_executable
1163*6777b538SAndroid Build Coastguard Worker                                         ? MemoryMappedFile::READ_CODE_IMAGE
1164*6777b538SAndroid Build Coastguard Worker                                         : MemoryMappedFile::READ_ONLY;
1165*6777b538SAndroid Build Coastguard Worker   MemoryMappedFile mapped_file;
1166*6777b538SAndroid Build Coastguard Worker   if (!mapped_file.Initialize(file_path, access)) {
1167*6777b538SAndroid Build Coastguard Worker     return false;
1168*6777b538SAndroid Build Coastguard Worker   }
1169*6777b538SAndroid Build Coastguard Worker 
1170*6777b538SAndroid Build Coastguard Worker   const ::SIZE_T length =
1171*6777b538SAndroid Build Coastguard Worker       std::min(base::saturated_cast<::SIZE_T>(max_bytes),
1172*6777b538SAndroid Build Coastguard Worker                base::saturated_cast<::SIZE_T>(mapped_file.length()));
1173*6777b538SAndroid Build Coastguard Worker   ::_WIN32_MEMORY_RANGE_ENTRY address_range = {mapped_file.data(), length};
1174*6777b538SAndroid Build Coastguard Worker   // Use ::PrefetchVirtualMemory(). This is better than a
1175*6777b538SAndroid Build Coastguard Worker   // simple data file read, more from a RAM perspective than CPU. This is
1176*6777b538SAndroid Build Coastguard Worker   // because reading the file as data results in double mapping to
1177*6777b538SAndroid Build Coastguard Worker   // Image/executable pages for all pages of code executed.
1178*6777b538SAndroid Build Coastguard Worker   return ::PrefetchVirtualMemory(::GetCurrentProcess(),
1179*6777b538SAndroid Build Coastguard Worker                                  /*NumberOfEntries=*/1, &address_range,
1180*6777b538SAndroid Build Coastguard Worker                                  /*Flags=*/0);
1181*6777b538SAndroid Build Coastguard Worker }
1182*6777b538SAndroid Build Coastguard Worker 
PreventExecuteMappingInternal(const FilePath & path,bool skip_path_check)1183*6777b538SAndroid Build Coastguard Worker bool PreventExecuteMappingInternal(const FilePath& path, bool skip_path_check) {
1184*6777b538SAndroid Build Coastguard Worker   if (!base::FeatureList::IsEnabled(
1185*6777b538SAndroid Build Coastguard Worker           features::kEnforceNoExecutableFileHandles)) {
1186*6777b538SAndroid Build Coastguard Worker     return true;
1187*6777b538SAndroid Build Coastguard Worker   }
1188*6777b538SAndroid Build Coastguard Worker 
1189*6777b538SAndroid Build Coastguard Worker   bool is_path_safe = skip_path_check || IsPathSafeToSetAclOn(path);
1190*6777b538SAndroid Build Coastguard Worker 
1191*6777b538SAndroid Build Coastguard Worker   if (!is_path_safe) {
1192*6777b538SAndroid Build Coastguard Worker     // To mitigate the effect of past OS bugs where attackers are able to use
1193*6777b538SAndroid Build Coastguard Worker     // writeable handles to create malicious executable images which can be
1194*6777b538SAndroid Build Coastguard Worker     // later mapped into unsandboxed processes, file handles that permit writing
1195*6777b538SAndroid Build Coastguard Worker     // that are passed to untrusted processes, e.g. renderers, should be marked
1196*6777b538SAndroid Build Coastguard Worker     // with a deny execute ACE. This prevents re-opening the file for execute
1197*6777b538SAndroid Build Coastguard Worker     // later on.
1198*6777b538SAndroid Build Coastguard Worker     //
1199*6777b538SAndroid Build Coastguard Worker     // To accomplish this, code that needs to pass writable file handles to a
1200*6777b538SAndroid Build Coastguard Worker     // renderer should open the file with the flags added by
1201*6777b538SAndroid Build Coastguard Worker     // `AddFlagsForPassingToUntrustedProcess()` (explicitly
1202*6777b538SAndroid Build Coastguard Worker     // FLAG_WIN_NO_EXECUTE). This results in this PreventExecuteMapping being
1203*6777b538SAndroid Build Coastguard Worker     // called by base::File.
1204*6777b538SAndroid Build Coastguard Worker     //
1205*6777b538SAndroid Build Coastguard Worker     // However, simply using this universally on all files that are opened
1206*6777b538SAndroid Build Coastguard Worker     // writeable is also undesirable: things can and will randomly break if they
1207*6777b538SAndroid Build Coastguard Worker     // are marked no-exec (e.g. marking an exe that the user downloads as
1208*6777b538SAndroid Build Coastguard Worker     // no-exec will prevent the user from running it). There are also
1209*6777b538SAndroid Build Coastguard Worker     // performance implications of doing this for all files unnecessarily.
1210*6777b538SAndroid Build Coastguard Worker     //
1211*6777b538SAndroid Build Coastguard Worker     // Code that passes writable files to the renderer is also expected to
1212*6777b538SAndroid Build Coastguard Worker     // reference files in places like the user data dir (e.g. for the filesystem
1213*6777b538SAndroid Build Coastguard Worker     // API) or temp files. Any attempt to pass a writeable handle to a path
1214*6777b538SAndroid Build Coastguard Worker     // outside these areas is likely its own security issue as an untrusted
1215*6777b538SAndroid Build Coastguard Worker     // renderer process should never have write access to e.g. system files or
1216*6777b538SAndroid Build Coastguard Worker     // downloads.
1217*6777b538SAndroid Build Coastguard Worker     //
1218*6777b538SAndroid Build Coastguard Worker     // This check aims to catch misuse of
1219*6777b538SAndroid Build Coastguard Worker     // `AddFlagsForPassingToUntrustedProcess()` on paths outside these
1220*6777b538SAndroid Build Coastguard Worker     // locations. Any time it hits it is also likely that a handle to a
1221*6777b538SAndroid Build Coastguard Worker     // dangerous path is being passed to a renderer, which is inherently unsafe.
1222*6777b538SAndroid Build Coastguard Worker     //
1223*6777b538SAndroid Build Coastguard Worker     // If this check hits, please do not ignore it but consult security team.
1224*6777b538SAndroid Build Coastguard Worker     DLOG(FATAL) << "Unsafe to deny execute access to path : " << path;
1225*6777b538SAndroid Build Coastguard Worker 
1226*6777b538SAndroid Build Coastguard Worker     return false;
1227*6777b538SAndroid Build Coastguard Worker   }
1228*6777b538SAndroid Build Coastguard Worker 
1229*6777b538SAndroid Build Coastguard Worker   static constexpr wchar_t kEveryoneSid[] = L"WD";
1230*6777b538SAndroid Build Coastguard Worker   auto sids = win::Sid::FromSddlStringVector({kEveryoneSid});
1231*6777b538SAndroid Build Coastguard Worker 
1232*6777b538SAndroid Build Coastguard Worker   // Remove executable access from the file. The API does not add a duplicate
1233*6777b538SAndroid Build Coastguard Worker   // ACE if it already exists.
1234*6777b538SAndroid Build Coastguard Worker   return win::DenyAccessToPath(path, *sids, FILE_EXECUTE, /*NO_INHERITANCE=*/0,
1235*6777b538SAndroid Build Coastguard Worker                                /*recursive=*/false);
1236*6777b538SAndroid Build Coastguard Worker }
1237*6777b538SAndroid Build Coastguard Worker 
PreventExecuteMapping(const FilePath & path)1238*6777b538SAndroid Build Coastguard Worker bool PreventExecuteMapping(const FilePath& path) {
1239*6777b538SAndroid Build Coastguard Worker   return PreventExecuteMappingInternal(path, false);
1240*6777b538SAndroid Build Coastguard Worker }
1241*6777b538SAndroid Build Coastguard Worker 
PreventExecuteMappingUnchecked(const FilePath & path,base::PassKey<PreventExecuteMappingClasses> passkey)1242*6777b538SAndroid Build Coastguard Worker bool PreventExecuteMappingUnchecked(
1243*6777b538SAndroid Build Coastguard Worker     const FilePath& path,
1244*6777b538SAndroid Build Coastguard Worker     base::PassKey<PreventExecuteMappingClasses> passkey) {
1245*6777b538SAndroid Build Coastguard Worker   return PreventExecuteMappingInternal(path, true);
1246*6777b538SAndroid Build Coastguard Worker }
1247*6777b538SAndroid Build Coastguard Worker 
SetExtraNoExecuteAllowedPath(int path_key)1248*6777b538SAndroid Build Coastguard Worker void SetExtraNoExecuteAllowedPath(int path_key) {
1249*6777b538SAndroid Build Coastguard Worker   DCHECK(!g_extra_allowed_path_for_no_execute ||
1250*6777b538SAndroid Build Coastguard Worker          g_extra_allowed_path_for_no_execute == path_key);
1251*6777b538SAndroid Build Coastguard Worker   g_extra_allowed_path_for_no_execute = path_key;
1252*6777b538SAndroid Build Coastguard Worker   base::FilePath valid_path;
1253*6777b538SAndroid Build Coastguard Worker   DCHECK(
1254*6777b538SAndroid Build Coastguard Worker       base::PathService::Get(g_extra_allowed_path_for_no_execute, &valid_path));
1255*6777b538SAndroid Build Coastguard Worker }
1256*6777b538SAndroid Build Coastguard Worker 
1257*6777b538SAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
1258*6777b538SAndroid Build Coastguard Worker 
1259*6777b538SAndroid Build Coastguard Worker namespace internal {
1260*6777b538SAndroid Build Coastguard Worker 
MoveUnsafe(const FilePath & from_path,const FilePath & to_path)1261*6777b538SAndroid Build Coastguard Worker bool MoveUnsafe(const FilePath& from_path, const FilePath& to_path) {
1262*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
1263*6777b538SAndroid Build Coastguard Worker 
1264*6777b538SAndroid Build Coastguard Worker   // NOTE: I suspect we could support longer paths, but that would involve
1265*6777b538SAndroid Build Coastguard Worker   // analyzing all our usage of files.
1266*6777b538SAndroid Build Coastguard Worker   if (from_path.value().length() >= MAX_PATH ||
1267*6777b538SAndroid Build Coastguard Worker       to_path.value().length() >= MAX_PATH) {
1268*6777b538SAndroid Build Coastguard Worker     return false;
1269*6777b538SAndroid Build Coastguard Worker   }
1270*6777b538SAndroid Build Coastguard Worker   if (MoveFileEx(from_path.value().c_str(), to_path.value().c_str(),
1271*6777b538SAndroid Build Coastguard Worker                  MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING) != 0)
1272*6777b538SAndroid Build Coastguard Worker     return true;
1273*6777b538SAndroid Build Coastguard Worker 
1274*6777b538SAndroid Build Coastguard Worker   // Keep the last error value from MoveFileEx around in case the below
1275*6777b538SAndroid Build Coastguard Worker   // fails.
1276*6777b538SAndroid Build Coastguard Worker   bool ret = false;
1277*6777b538SAndroid Build Coastguard Worker   DWORD last_error = ::GetLastError();
1278*6777b538SAndroid Build Coastguard Worker 
1279*6777b538SAndroid Build Coastguard Worker   if (DirectoryExists(from_path)) {
1280*6777b538SAndroid Build Coastguard Worker     // MoveFileEx fails if moving directory across volumes. We will simulate
1281*6777b538SAndroid Build Coastguard Worker     // the move by using Copy and Delete. Ideally we could check whether
1282*6777b538SAndroid Build Coastguard Worker     // from_path and to_path are indeed in different volumes.
1283*6777b538SAndroid Build Coastguard Worker     ret = internal::CopyAndDeleteDirectory(from_path, to_path);
1284*6777b538SAndroid Build Coastguard Worker   }
1285*6777b538SAndroid Build Coastguard Worker 
1286*6777b538SAndroid Build Coastguard Worker   if (!ret) {
1287*6777b538SAndroid Build Coastguard Worker     // Leave a clue about what went wrong so that it can be (at least) picked
1288*6777b538SAndroid Build Coastguard Worker     // up by a PLOG entry.
1289*6777b538SAndroid Build Coastguard Worker     ::SetLastError(last_error);
1290*6777b538SAndroid Build Coastguard Worker   }
1291*6777b538SAndroid Build Coastguard Worker 
1292*6777b538SAndroid Build Coastguard Worker   return ret;
1293*6777b538SAndroid Build Coastguard Worker }
1294*6777b538SAndroid Build Coastguard Worker 
CopyAndDeleteDirectory(const FilePath & from_path,const FilePath & to_path)1295*6777b538SAndroid Build Coastguard Worker bool CopyAndDeleteDirectory(const FilePath& from_path,
1296*6777b538SAndroid Build Coastguard Worker                             const FilePath& to_path) {
1297*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
1298*6777b538SAndroid Build Coastguard Worker   if (CopyDirectory(from_path, to_path, true)) {
1299*6777b538SAndroid Build Coastguard Worker     if (DeletePathRecursively(from_path))
1300*6777b538SAndroid Build Coastguard Worker       return true;
1301*6777b538SAndroid Build Coastguard Worker 
1302*6777b538SAndroid Build Coastguard Worker     // Like Move, this function is not transactional, so we just
1303*6777b538SAndroid Build Coastguard Worker     // leave the copied bits behind if deleting from_path fails.
1304*6777b538SAndroid Build Coastguard Worker     // If to_path exists previously then we have already overwritten
1305*6777b538SAndroid Build Coastguard Worker     // it by now, we don't get better off by deleting the new bits.
1306*6777b538SAndroid Build Coastguard Worker   }
1307*6777b538SAndroid Build Coastguard Worker   return false;
1308*6777b538SAndroid Build Coastguard Worker }
1309*6777b538SAndroid Build Coastguard Worker 
1310*6777b538SAndroid Build Coastguard Worker }  // namespace internal
1311*6777b538SAndroid Build Coastguard Worker }  // namespace base
1312