xref: /aosp_15_r20/external/cronet/base/files/file_util_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/files/file_util.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 
11 #include <algorithm>
12 #include <fstream>
13 #include <initializer_list>
14 #include <memory>
15 #include <set>
16 #include <utility>
17 #include <vector>
18 
19 #include "base/base_paths.h"
20 #include "base/command_line.h"
21 #include "base/environment.h"
22 #include "base/features.h"
23 #include "base/files/file.h"
24 #include "base/files/file_enumerator.h"
25 #include "base/files/file_path.h"
26 #include "base/files/platform_file.h"
27 #include "base/files/scoped_file.h"
28 #include "base/files/scoped_temp_dir.h"
29 #include "base/functional/bind.h"
30 #include "base/functional/callback_helpers.h"
31 #include "base/logging.h"
32 #include "base/path_service.h"
33 #include "base/rand_util.h"
34 #include "base/scoped_environment_variable_override.h"
35 #include "base/strings/string_util.h"
36 #include "base/strings/stringprintf.h"
37 #include "base/strings/utf_string_conversions.h"
38 #include "base/test/bind.h"
39 #include "base/test/multiprocess_test.h"
40 #include "base/test/scoped_feature_list.h"
41 #include "base/test/task_environment.h"
42 #include "base/test/test_file_util.h"
43 #include "base/test/test_timeouts.h"
44 #include "base/threading/platform_thread.h"
45 #include "base/threading/thread.h"
46 #include "base/time/time.h"
47 #include "base/uuid.h"
48 #include "build/branding_buildflags.h"
49 #include "build/build_config.h"
50 #include "testing/gtest/include/gtest/gtest.h"
51 #include "testing/multiprocess_func_list.h"
52 #include "testing/platform_test.h"
53 
54 #if BUILDFLAG(IS_WIN)
55 #include <tchar.h>
56 #include <windows.h>
57 
58 #include <shellapi.h>
59 #include <shlobj.h>
60 
61 #include "base/scoped_native_library.h"
62 #include "base/strings/string_number_conversions.h"
63 #include "base/test/file_path_reparse_point_win.h"
64 #include "base/test/gtest_util.h"
65 #include "base/win/scoped_handle.h"
66 #include "base/win/win_util.h"
67 #endif
68 
69 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
70 #include <errno.h>
71 #include <fcntl.h>
72 #include <sys/ioctl.h>
73 #include <sys/types.h>
74 #include <unistd.h>
75 #endif
76 
77 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
78 #include <sys/socket.h>
79 #endif
80 
81 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
82 #include <linux/fs.h>
83 #endif
84 
85 #if BUILDFLAG(IS_ANDROID)
86 #include "base/android/content_uri_utils.h"
87 #endif
88 
89 #if BUILDFLAG(IS_FUCHSIA)
90 #include "base/test/scoped_dev_zero_fuchsia.h"
91 #endif
92 
93 // This macro helps avoid wrapped lines in the test structs.
94 #define FPL(x) FILE_PATH_LITERAL(x)
95 
96 namespace base {
97 
98 namespace {
99 
100 const size_t kLargeFileSize = (1 << 16) + 3;
101 
102 enum class CreateSymbolicLinkResult {
103   // The symbolic link creation failed because the platform does not support it.
104   // On Windows, that may be due to the lack of the required privilege.
105   kUnsupported = -1,
106 
107   // The symbolic link creation failed.
108   kFailed,
109 
110   // The symbolic link was created successfully.
111   kSucceeded,
112 };
113 
114 #if BUILDFLAG(IS_WIN)
115 // Method that wraps the win32 GetShortPathName API. Returns an empty path on
116 // error.
MakeShortFilePath(const FilePath & input)117 FilePath MakeShortFilePath(const FilePath& input) {
118   DWORD path_short_len = ::GetShortPathName(input.value().c_str(), nullptr, 0);
119   if (path_short_len == 0UL)
120     return FilePath();
121 
122   std::wstring path_short_str;
123   path_short_len = ::GetShortPathName(
124       input.value().c_str(), WriteInto(&path_short_str, path_short_len),
125       path_short_len);
126   if (path_short_len == 0UL)
127     return FilePath();
128 
129   return FilePath(path_short_str);
130 }
131 
CreateWinSymbolicLink(const FilePath & target,const FilePath & symlink)132 CreateSymbolicLinkResult CreateWinSymbolicLink(const FilePath& target,
133                                                const FilePath& symlink) {
134   // Determine whether the target is a directory. This is necessary because
135   // creating a symbolic link requires different flags depending on the type
136   // of the target (file vs. directory).
137   DWORD attrs = GetFileAttributes(target.value().c_str());
138   if (attrs == INVALID_FILE_ATTRIBUTES) {
139     // Unable to retrieve attributes for the target. It might not exist, or
140     // there may be a permissions issue. Either way, we cannot proceed.
141     return CreateSymbolicLinkResult::kFailed;
142   }
143 
144   DWORD flags =
145       attrs & FILE_ATTRIBUTE_DIRECTORY ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0;
146 
147   if (!::CreateSymbolicLink(
148           symlink.value().c_str(), target.value().c_str(),
149           flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) {
150     if (::GetLastError() == ERROR_PRIVILEGE_NOT_HELD) {
151       return CreateSymbolicLinkResult::kUnsupported;
152     }
153     return CreateSymbolicLinkResult::kFailed;
154   }
155 
156   return CreateSymbolicLinkResult::kSucceeded;
157 }
158 #endif  // BUILDFLAG(IS_WIN)
159 
160 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_POSIX)
161 
CreateSymbolicLinkForTesting(const FilePath & target,const FilePath & symlink)162 CreateSymbolicLinkResult CreateSymbolicLinkForTesting(const FilePath& target,
163                                                       const FilePath& symlink) {
164 #if BUILDFLAG(IS_WIN)
165   return CreateWinSymbolicLink(target, symlink);
166 #else
167   if (!CreateSymbolicLink(target, symlink)) {
168     return CreateSymbolicLinkResult::kFailed;
169   }
170   return CreateSymbolicLinkResult::kSucceeded;
171 #endif  // BUILDFLAG(IS_WIN)
172 }
173 
174 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_POSIX)
175 
176 #if BUILDFLAG(IS_MAC)
177 // Provide a simple way to change the permissions bits on |path| in tests.
178 // ASSERT failures will return, but not stop the test.  Caller should wrap
179 // calls to this function in ASSERT_NO_FATAL_FAILURE().
ChangePosixFilePermissions(const FilePath & path,int mode_bits_to_set,int mode_bits_to_clear)180 void ChangePosixFilePermissions(const FilePath& path,
181                                 int mode_bits_to_set,
182                                 int mode_bits_to_clear) {
183   ASSERT_FALSE(mode_bits_to_set & mode_bits_to_clear)
184       << "Can't set and clear the same bits.";
185 
186   int mode = 0;
187   ASSERT_TRUE(GetPosixFilePermissions(path, &mode));
188   mode |= mode_bits_to_set;
189   mode &= ~mode_bits_to_clear;
190   ASSERT_TRUE(SetPosixFilePermissions(path, mode));
191 }
192 #endif  // BUILDFLAG(IS_MAC)
193 
194 // Fuchsia doesn't support file permissions.
195 #if !BUILDFLAG(IS_FUCHSIA)
196 // Sets the source file to read-only.
SetReadOnly(const FilePath & path,bool read_only)197 void SetReadOnly(const FilePath& path, bool read_only) {
198 #if BUILDFLAG(IS_WIN)
199   // On Windows, it involves setting/removing the 'readonly' bit.
200   DWORD attrs = GetFileAttributes(path.value().c_str());
201   ASSERT_NE(INVALID_FILE_ATTRIBUTES, attrs);
202   ASSERT_TRUE(SetFileAttributes(
203       path.value().c_str(), read_only ? (attrs | FILE_ATTRIBUTE_READONLY)
204                                       : (attrs & ~FILE_ATTRIBUTE_READONLY)));
205 
206   DWORD expected =
207       read_only
208           ? ((attrs & (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DIRECTORY)) |
209              FILE_ATTRIBUTE_READONLY)
210           : (attrs & (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DIRECTORY));
211 
212   // Ignore FILE_ATTRIBUTE_NOT_CONTENT_INDEXED and FILE_ATTRIBUTE_COMPRESSED
213   // if present. These flags are set by the operating system, depending on
214   // local configurations, such as compressing the file system. Not filtering
215   // out these flags could cause tests to fail even though they should pass.
216   attrs = GetFileAttributes(path.value().c_str()) &
217           ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_COMPRESSED);
218   ASSERT_EQ(expected, attrs);
219 #else
220   // On all other platforms, it involves removing/setting the write bit.
221   mode_t mode = read_only ? S_IRUSR : (S_IRUSR | S_IWUSR);
222   EXPECT_TRUE(SetPosixFilePermissions(
223       path, DirectoryExists(path) ? (mode | S_IXUSR) : mode));
224 #endif  // BUILDFLAG(IS_WIN)
225 }
226 
IsReadOnly(const FilePath & path)227 bool IsReadOnly(const FilePath& path) {
228 #if BUILDFLAG(IS_WIN)
229   DWORD attrs = GetFileAttributes(path.value().c_str());
230   EXPECT_NE(INVALID_FILE_ATTRIBUTES, attrs);
231   return attrs & FILE_ATTRIBUTE_READONLY;
232 #else
233   int mode = 0;
234   EXPECT_TRUE(GetPosixFilePermissions(path, &mode));
235   return !(mode & S_IWUSR);
236 #endif  // BUILDFLAG(IS_WIN)
237 }
238 
239 #endif  // BUILDFLAG(IS_FUCHSIA)
240 
241 const wchar_t bogus_content[] = L"I'm cannon fodder.";
242 
243 const int FILES_AND_DIRECTORIES =
244     FileEnumerator::FILES | FileEnumerator::DIRECTORIES;
245 
246 // file_util winds up using autoreleased objects on the Mac, so this needs
247 // to be a PlatformTest
248 class FileUtilTest : public PlatformTest {
249  protected:
SetUp()250   void SetUp() override {
251     PlatformTest::SetUp();
252     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
253   }
254 
255   ScopedTempDir temp_dir_;
256 };
257 
258 // Collects all the results from the given file enumerator, and provides an
259 // interface to query whether a given file is present.
260 class FindResultCollector {
261  public:
FindResultCollector(FileEnumerator * enumerator)262   explicit FindResultCollector(FileEnumerator* enumerator) {
263     FilePath cur_file;
264     while (!(cur_file = enumerator->Next()).value().empty()) {
265       FilePath::StringType path = cur_file.value();
266       // The file should not be returned twice.
267       EXPECT_TRUE(files_.end() == files_.find(path))
268           << "Same file returned twice";
269 
270       // Save for later.
271       files_.insert(path);
272     }
273   }
274 
275   // Returns true if the enumerator found the file.
HasFile(const FilePath & file) const276   bool HasFile(const FilePath& file) const {
277     return files_.find(file.value()) != files_.end();
278   }
279 
size()280   int size() {
281     return static_cast<int>(files_.size());
282   }
283 
284  private:
285   std::set<FilePath::StringType> files_;
286 };
287 
288 // Simple function to dump some text into a new file.
CreateTextFile(const FilePath & filename,const std::wstring & contents)289 void CreateTextFile(const FilePath& filename,
290                     const std::wstring& contents) {
291   std::wofstream file;
292 #if BUILDFLAG(IS_WIN)
293   file.open(filename.value().c_str());
294 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
295   file.open(filename.value());
296 #endif  // BUILDFLAG(IS_WIN)
297   ASSERT_TRUE(file.is_open());
298   file << contents;
299   file.close();
300 }
301 
302 // Simple function to take out some text from a file.
ReadTextFile(const FilePath & filename)303 std::wstring ReadTextFile(const FilePath& filename) {
304   wchar_t contents[64];
305   std::wifstream file;
306 #if BUILDFLAG(IS_WIN)
307   file.open(filename.value().c_str());
308 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
309   file.open(filename.value());
310 #endif  // BUILDFLAG(IS_WIN)
311   EXPECT_TRUE(file.is_open());
312   file.getline(contents, std::size(contents));
313   file.close();
314   return std::wstring(contents);
315 }
316 
317 // Sets |is_inheritable| to indicate whether or not |stream| is set up to be
318 // inerhited into child processes (i.e., HANDLE_FLAG_INHERIT is set on the
319 // underlying handle on Windows, or FD_CLOEXEC is not set on the underlying file
320 // descriptor on POSIX). Calls to this function must be wrapped with
321 // ASSERT_NO_FATAL_FAILURE to properly abort tests in case of fatal failure.
GetIsInheritable(FILE * stream,bool * is_inheritable)322 void GetIsInheritable(FILE* stream, bool* is_inheritable) {
323 #if BUILDFLAG(IS_WIN)
324   HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(stream)));
325   ASSERT_NE(INVALID_HANDLE_VALUE, handle);
326 
327   DWORD info = 0;
328   ASSERT_EQ(TRUE, ::GetHandleInformation(handle, &info));
329   *is_inheritable = ((info & HANDLE_FLAG_INHERIT) != 0);
330 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
331   int fd = fileno(stream);
332   ASSERT_NE(-1, fd);
333   int flags = fcntl(fd, F_GETFD, 0);
334   ASSERT_NE(-1, flags);
335   *is_inheritable = ((flags & FD_CLOEXEC) == 0);
336 #else
337 #error Not implemented
338 #endif
339 }
340 
341 #if BUILDFLAG(IS_POSIX)
342 class ScopedWorkingDirectory {
343  public:
ScopedWorkingDirectory(const FilePath & new_working_dir)344   explicit ScopedWorkingDirectory(const FilePath& new_working_dir) {
345     CHECK(base::GetCurrentDirectory(&original_working_directory_));
346     CHECK(base::SetCurrentDirectory(new_working_dir));
347   }
348 
~ScopedWorkingDirectory()349   ~ScopedWorkingDirectory() {
350     CHECK(base::SetCurrentDirectory(original_working_directory_));
351   }
352 
353  private:
354   base::FilePath original_working_directory_;
355 };
356 
TEST_F(FileUtilTest,MakeAbsoluteFilePathNoResolveSymbolicLinks)357 TEST_F(FileUtilTest, MakeAbsoluteFilePathNoResolveSymbolicLinks) {
358   FilePath cwd;
359   ASSERT_TRUE(GetCurrentDirectory(&cwd));
360   const std::pair<FilePath, std::optional<FilePath>> kExpectedResults[]{
361       {FilePath(), std::nullopt},
362       {FilePath("."), cwd},
363       {FilePath(".."), cwd.DirName()},
364       {FilePath("a/.."), cwd},
365       {FilePath("a/b/.."), cwd.Append(FPL("a"))},
366       {FilePath("/tmp/../.."), FilePath("/")},
367       {FilePath("/tmp/../"), FilePath("/")},
368       {FilePath("/tmp/a/b/../c/../.."), FilePath("/tmp")},
369       {FilePath("/././tmp/./a/./b/../c/./../.."), FilePath("/tmp")},
370       {FilePath("/.././../tmp"), FilePath("/tmp")},
371       {FilePath("/..///.////..////tmp"), FilePath("/tmp")},
372       {FilePath("//..///.////..////tmp"), FilePath("//tmp")},
373       {FilePath("///..///.////..////tmp"), FilePath("/tmp")},
374   };
375 
376   for (auto& expected_result : kExpectedResults) {
377     EXPECT_EQ(MakeAbsoluteFilePathNoResolveSymbolicLinks(expected_result.first),
378               expected_result.second);
379   }
380 
381   // Test that MakeAbsoluteFilePathNoResolveSymbolicLinks() returns an empty
382   // path if GetCurrentDirectory() fails.
383   const FilePath temp_dir_path = temp_dir_.GetPath();
384   ScopedWorkingDirectory scoped_cwd(temp_dir_path);
385   // Delete the cwd so that GetCurrentDirectory() fails.
386   ASSERT_TRUE(temp_dir_.Delete());
387   ASSERT_FALSE(
388       MakeAbsoluteFilePathNoResolveSymbolicLinks(FilePath("relative_file_path"))
389           .has_value());
390 }
391 #endif  // BUILDFLAG(IS_POSIX)
392 
TEST_F(FileUtilTest,FileAndDirectorySize)393 TEST_F(FileUtilTest, FileAndDirectorySize) {
394   // Create three files of 20, 30 and 3 chars (utf8). ComputeDirectorySize
395   // should return 53 bytes.
396   FilePath file_01 = temp_dir_.GetPath().Append(FPL("The file 01.txt"));
397   CreateTextFile(file_01, L"12345678901234567890");
398   int64_t size_f1 = 0;
399   ASSERT_TRUE(GetFileSize(file_01, &size_f1));
400   EXPECT_EQ(20ll, size_f1);
401 
402   FilePath subdir_path = temp_dir_.GetPath().Append(FPL("Level2"));
403   CreateDirectory(subdir_path);
404 
405   FilePath file_02 = subdir_path.Append(FPL("The file 02.txt"));
406   CreateTextFile(file_02, L"123456789012345678901234567890");
407   int64_t size_f2 = 0;
408   ASSERT_TRUE(GetFileSize(file_02, &size_f2));
409   EXPECT_EQ(30ll, size_f2);
410 
411   FilePath subsubdir_path = subdir_path.Append(FPL("Level3"));
412   CreateDirectory(subsubdir_path);
413 
414   FilePath file_03 = subsubdir_path.Append(FPL("The file 03.txt"));
415   CreateTextFile(file_03, L"123");
416 
417   int64_t computed_size = ComputeDirectorySize(temp_dir_.GetPath());
418   EXPECT_EQ(size_f1 + size_f2 + 3, computed_size);
419 }
420 
TEST_F(FileUtilTest,NormalizeFilePathBasic)421 TEST_F(FileUtilTest, NormalizeFilePathBasic) {
422   // Create a directory under the test dir.  Because we create it,
423   // we know it is not a link.
424   FilePath file_a_path = temp_dir_.GetPath().Append(FPL("file_a"));
425   FilePath dir_path = temp_dir_.GetPath().Append(FPL("dir"));
426   FilePath file_b_path = dir_path.Append(FPL("file_b"));
427   CreateDirectory(dir_path);
428 
429   FilePath normalized_file_a_path, normalized_file_b_path;
430   ASSERT_FALSE(PathExists(file_a_path));
431   ASSERT_FALSE(NormalizeFilePath(file_a_path, &normalized_file_a_path))
432     << "NormalizeFilePath() should fail on nonexistent paths.";
433 
434   CreateTextFile(file_a_path, bogus_content);
435   ASSERT_TRUE(PathExists(file_a_path));
436   ASSERT_TRUE(NormalizeFilePath(file_a_path, &normalized_file_a_path));
437 
438   CreateTextFile(file_b_path, bogus_content);
439   ASSERT_TRUE(PathExists(file_b_path));
440   ASSERT_TRUE(NormalizeFilePath(file_b_path, &normalized_file_b_path));
441 
442   // Because this test created |dir_path|, we know it is not a link
443   // or junction.  So, the real path of the directory holding file a
444   // must be the parent of the path holding file b.
445   ASSERT_TRUE(normalized_file_a_path.DirName()
446       .IsParent(normalized_file_b_path.DirName()));
447 }
448 
449 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_POSIX)
450 
TEST_F(FileUtilTest,IsLinkCreateSymbolicLinkOnFile)451 TEST_F(FileUtilTest, IsLinkCreateSymbolicLinkOnFile) {
452   FilePath target_file_path;
453   ASSERT_TRUE(CreateTemporaryFileInDir(temp_dir_.GetPath(), &target_file_path));
454   EXPECT_FALSE(IsLink(target_file_path));
455 
456   base::FilePath symlink_path =
457       temp_dir_.GetPath().Append(FPL("symlink_to_target"));
458 
459   CreateSymbolicLinkResult result =
460       CreateSymbolicLinkForTesting(target_file_path, symlink_path);
461   if (result == CreateSymbolicLinkResult::kUnsupported) {
462     GTEST_SKIP();
463   }
464   ASSERT_EQ(result, CreateSymbolicLinkResult::kSucceeded);
465 
466   EXPECT_TRUE(IsLink(symlink_path));
467 }
468 
TEST_F(FileUtilTest,IsLinkCreateSymbolicLinkOnDirectory)469 TEST_F(FileUtilTest, IsLinkCreateSymbolicLinkOnDirectory) {
470   FilePath target_path = temp_dir_.GetPath().Append(FPL("target"));
471   ASSERT_TRUE(CreateDirectory(target_path));
472   EXPECT_FALSE(IsLink(target_path));
473 
474   base::FilePath symlink_path =
475       temp_dir_.GetPath().Append(FPL("symlink_to_target"));
476 
477   CreateSymbolicLinkResult result =
478       CreateSymbolicLinkForTesting(target_path, symlink_path);
479   if (result == CreateSymbolicLinkResult::kUnsupported) {
480     GTEST_SKIP();
481   }
482   ASSERT_EQ(result, CreateSymbolicLinkResult::kSucceeded);
483 
484   EXPECT_TRUE(IsLink(symlink_path));
485 }
486 
TEST_F(FileUtilTest,IsLinkMissingFile)487 TEST_F(FileUtilTest, IsLinkMissingFile) {
488   EXPECT_FALSE(IsLink(FilePath()));
489 }
490 
TEST_F(FileUtilTest,IsLinkWithDeletedTargetFile)491 TEST_F(FileUtilTest, IsLinkWithDeletedTargetFile) {
492   // Set up a symlink pointing to a temporary file.
493   FilePath target_file_path;
494   ASSERT_TRUE(CreateTemporaryFileInDir(temp_dir_.GetPath(), &target_file_path));
495   FilePath symlink_path =
496       temp_dir_.GetPath().Append(FPL("symlink_to_missing_target"));
497 
498   CreateSymbolicLinkResult result =
499       CreateSymbolicLinkForTesting(target_file_path, symlink_path);
500   if (result == CreateSymbolicLinkResult::kUnsupported) {
501     GTEST_SKIP();
502   }
503   ASSERT_EQ(result, CreateSymbolicLinkResult::kSucceeded);
504 
505   // Verify that the symlink is recognized correctly.
506   EXPECT_TRUE(IsLink(symlink_path));
507 
508   // Delete the target file.
509   ASSERT_TRUE(DeleteFile(target_file_path));
510 
511   // Verify that IsLink still returns true for the symlink, even though its
512   // target is missing.
513   EXPECT_TRUE(IsLink(symlink_path));
514 }
515 
TEST_F(FileUtilTest,IsLinkWithDeletedTargetDirectory)516 TEST_F(FileUtilTest, IsLinkWithDeletedTargetDirectory) {
517   // Set up a symlink pointing to a temporary file.
518   FilePath target_path = temp_dir_.GetPath().Append(FPL("target"));
519   ASSERT_TRUE(CreateDirectory(target_path));
520   FilePath symlink_path =
521       temp_dir_.GetPath().Append(FPL("symlink_to_missing_target"));
522 
523   CreateSymbolicLinkResult result =
524       CreateSymbolicLinkForTesting(target_path, symlink_path);
525   if (result == CreateSymbolicLinkResult::kUnsupported) {
526     GTEST_SKIP();
527   }
528   ASSERT_EQ(result, CreateSymbolicLinkResult::kSucceeded);
529 
530   // Verify that the symlink is recognized correctly.
531   EXPECT_TRUE(IsLink(symlink_path));
532 
533   // Delete the target file.
534   ASSERT_TRUE(DeleteFile(target_path));
535 
536   // Verify that IsLink still returns true for the symlink, even though its
537   // target is missing.
538   EXPECT_TRUE(IsLink(symlink_path));
539 }
540 
TEST_F(FileUtilTest,IsLinkWihtoutReparsePointAttributeOnDirectory)541 TEST_F(FileUtilTest, IsLinkWihtoutReparsePointAttributeOnDirectory) {
542   FilePath target_path = temp_dir_.GetPath().Append(FPL("target"));
543   ASSERT_TRUE(CreateDirectory(target_path));
544   EXPECT_FALSE(IsLink(target_path));
545 }
546 
TEST_F(FileUtilTest,IsLinkWihtoutReparsePointAttributeOnFile)547 TEST_F(FileUtilTest, IsLinkWihtoutReparsePointAttributeOnFile) {
548   FilePath target_file_path;
549   ASSERT_TRUE(CreateTemporaryFileInDir(temp_dir_.GetPath(), &target_file_path));
550   EXPECT_FALSE(IsLink(target_file_path));
551 }
552 
553 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_POSIX)
554 
555 #if BUILDFLAG(IS_WIN)
556 
TEST_F(FileUtilTest,NormalizeFileEmptyFile)557 TEST_F(FileUtilTest, NormalizeFileEmptyFile) {
558   // Create a directory under the test dir.  Because we create it,
559   // we know it is not a link.
560   const wchar_t empty_content[] = L"";
561 
562   FilePath file_a_path = temp_dir_.GetPath().Append(FPL("file_empty_a"));
563   FilePath dir_path = temp_dir_.GetPath().Append(FPL("dir"));
564   FilePath file_b_path = dir_path.Append(FPL("file_empty_b"));
565   ASSERT_TRUE(CreateDirectory(dir_path));
566 
567   FilePath normalized_file_a_path, normalized_file_b_path;
568   ASSERT_FALSE(PathExists(file_a_path));
569   EXPECT_FALSE(NormalizeFilePath(file_a_path, &normalized_file_a_path))
570       << "NormalizeFilePath() should fail on nonexistent paths.";
571 
572   CreateTextFile(file_a_path, empty_content);
573   ASSERT_TRUE(PathExists(file_a_path));
574   EXPECT_TRUE(NormalizeFilePath(file_a_path, &normalized_file_a_path));
575 
576   CreateTextFile(file_b_path, empty_content);
577   ASSERT_TRUE(PathExists(file_b_path));
578   EXPECT_TRUE(NormalizeFilePath(file_b_path, &normalized_file_b_path));
579 
580   // Because this test created |dir_path|, we know it is not a link
581   // or junction.  So, the real path of the directory holding file a
582   // must be the parent of the path holding file b.
583   EXPECT_TRUE(normalized_file_a_path.DirName().IsParent(
584       normalized_file_b_path.DirName()));
585 }
586 
TEST_F(FileUtilTest,NormalizeFilePathReparsePoints)587 TEST_F(FileUtilTest, NormalizeFilePathReparsePoints) {
588   // Build the following directory structure:
589   //
590   // temp_dir
591   // |-> base_a
592   // |   |-> sub_a
593   // |       |-> file.txt
594   // |       |-> long_name___... (Very long name.)
595   // |           |-> sub_long
596   // |              |-> deep.txt
597   // |-> base_b
598   //     |-> to_sub_a (reparse point to temp_dir\base_a\sub_a)
599   //     |-> to_base_b (reparse point to temp_dir\base_b)
600   //     |-> to_sub_long (reparse point to temp_dir\sub_a\long_name_\sub_long)
601 
602   FilePath base_a = temp_dir_.GetPath().Append(FPL("base_a"));
603 #if BUILDFLAG(IS_WIN)
604   // TEMP can have a lower case drive letter.
605   std::wstring temp_base_a = base_a.value();
606   ASSERT_FALSE(temp_base_a.empty());
607   temp_base_a[0] = ToUpperASCII(char16_t{temp_base_a[0]});
608   base_a = FilePath(temp_base_a);
609 #endif
610   ASSERT_TRUE(CreateDirectory(base_a));
611 #if BUILDFLAG(IS_WIN)
612   // TEMP might be a short name which is not normalized.
613   base_a = MakeLongFilePath(base_a);
614 #endif
615 
616   FilePath sub_a = base_a.Append(FPL("sub_a"));
617   ASSERT_TRUE(CreateDirectory(sub_a));
618 
619   FilePath file_txt = sub_a.Append(FPL("file.txt"));
620   CreateTextFile(file_txt, bogus_content);
621 
622   // Want a directory whose name is long enough to make the path to the file
623   // inside just under MAX_PATH chars.  This will be used to test that when
624   // a junction expands to a path over MAX_PATH chars in length,
625   // NormalizeFilePath() fails without crashing.
626   FilePath sub_long_rel(FPL("sub_long"));
627   FilePath deep_txt(FPL("deep.txt"));
628 
629   int target_length = MAX_PATH;
630   target_length -= (sub_a.value().length() + 1);  // +1 for the sepperator '\'.
631   target_length -= (sub_long_rel.Append(deep_txt).value().length() + 1);
632   // Without making the path a bit shorter, CreateDirectory() fails.
633   // the resulting path is still long enough to hit the failing case in
634   // NormalizePath().
635   const int kCreateDirLimit = 4;
636   target_length -= kCreateDirLimit;
637   FilePath::StringType long_name_str = FPL("long_name_");
638   long_name_str.resize(target_length, '_');
639 
640   FilePath long_name = sub_a.Append(FilePath(long_name_str));
641   FilePath deep_file = long_name.Append(sub_long_rel).Append(deep_txt);
642   ASSERT_EQ(static_cast<size_t>(MAX_PATH - kCreateDirLimit),
643             deep_file.value().length());
644 
645   FilePath sub_long = deep_file.DirName();
646   ASSERT_TRUE(CreateDirectory(sub_long));
647   CreateTextFile(deep_file, bogus_content);
648 
649   FilePath base_b = temp_dir_.GetPath().Append(FPL("base_b"));
650   ASSERT_TRUE(CreateDirectory(base_b));
651 #if BUILDFLAG(IS_WIN)
652   // TEMP might be a short name which is not normalized.
653   base_b = MakeLongFilePath(base_b);
654 #endif
655 
656   FilePath to_sub_a = base_b.Append(FPL("to_sub_a"));
657   ASSERT_TRUE(CreateDirectory(to_sub_a));
658   FilePath normalized_path;
659   {
660     auto reparse_to_sub_a = test::FilePathReparsePoint::Create(to_sub_a, sub_a);
661     ASSERT_TRUE(reparse_to_sub_a.has_value());
662 
663     FilePath to_base_b = base_b.Append(FPL("to_base_b"));
664     ASSERT_TRUE(CreateDirectory(to_base_b));
665     auto reparse_to_base_b =
666         test::FilePathReparsePoint::Create(to_base_b, base_b);
667     ASSERT_TRUE(reparse_to_base_b.has_value());
668 
669     FilePath to_sub_long = base_b.Append(FPL("to_sub_long"));
670     ASSERT_TRUE(CreateDirectory(to_sub_long));
671     auto reparse_to_sub_long =
672         test::FilePathReparsePoint::Create(to_sub_long, sub_long);
673     ASSERT_TRUE(reparse_to_sub_long.has_value());
674 
675     // Normalize a junction free path: base_a\sub_a\file.txt .
676     ASSERT_TRUE(NormalizeFilePath(file_txt, &normalized_path));
677     ASSERT_EQ(file_txt.value(), normalized_path.value());
678 
679     // Check that the path base_b\to_sub_a\file.txt can be normalized to exclude
680     // the junction to_sub_a.
681     ASSERT_TRUE(NormalizeFilePath(to_sub_a.Append(FPL("file.txt")),
682                                              &normalized_path));
683     ASSERT_EQ(file_txt.value(), normalized_path.value());
684 
685     // Check that the path base_b\to_base_b\to_base_b\to_sub_a\file.txt can be
686     // normalized to exclude junctions to_base_b and to_sub_a .
687     ASSERT_TRUE(NormalizeFilePath(base_b.Append(FPL("to_base_b"))
688                                                    .Append(FPL("to_base_b"))
689                                                    .Append(FPL("to_sub_a"))
690                                                    .Append(FPL("file.txt")),
691                                              &normalized_path));
692     ASSERT_EQ(file_txt.value(), normalized_path.value());
693 
694     // A long enough path will cause NormalizeFilePath() to fail.  Make a long
695     // path using to_base_b many times, and check that paths long enough to fail
696     // do not cause a crash.
697     FilePath long_path = base_b;
698     const int kLengthLimit = MAX_PATH + 200;
699     while (long_path.value().length() <= kLengthLimit) {
700       long_path = long_path.Append(FPL("to_base_b"));
701     }
702     long_path = long_path.Append(FPL("to_sub_a"))
703                          .Append(FPL("file.txt"));
704 
705     ASSERT_FALSE(NormalizeFilePath(long_path, &normalized_path));
706 
707     // Normalizing the junction to deep.txt should fail, because the expanded
708     // path to deep.txt is longer than MAX_PATH.
709     ASSERT_FALSE(NormalizeFilePath(to_sub_long.Append(deep_txt),
710                                               &normalized_path));
711 
712     // Delete the reparse points, and see that NormalizeFilePath() fails
713     // to traverse them.
714   }
715 
716   ASSERT_FALSE(NormalizeFilePath(to_sub_a.Append(FPL("file.txt")),
717                                             &normalized_path));
718 }
719 
TEST_F(FileUtilTest,DevicePathToDriveLetter)720 TEST_F(FileUtilTest, DevicePathToDriveLetter) {
721   // Get a drive letter.
722   std::wstring real_drive_letter = AsWString(
723       ToUpperASCII(AsStringPiece16(temp_dir_.GetPath().value().substr(0, 2))));
724   if (!IsAsciiAlpha(real_drive_letter[0]) || ':' != real_drive_letter[1]) {
725     LOG(ERROR) << "Can't get a drive letter to test with.";
726     return;
727   }
728 
729   // Get the NT style path to that drive.
730   wchar_t device_path[MAX_PATH] = {'\0'};
731   ASSERT_TRUE(
732       ::QueryDosDevice(real_drive_letter.c_str(), device_path, MAX_PATH));
733   FilePath actual_device_path(device_path);
734   FilePath win32_path;
735 
736   // Run DevicePathToDriveLetterPath() on the NT style path we got from
737   // QueryDosDevice().  Expect the drive letter we started with.
738   ASSERT_TRUE(DevicePathToDriveLetterPath(actual_device_path, &win32_path));
739   ASSERT_EQ(real_drive_letter, win32_path.value());
740 
741   // Add some directories to the path.  Expect those extra path componenets
742   // to be preserved.
743   FilePath kRelativePath(FPL("dir1\\dir2\\file.txt"));
744   ASSERT_TRUE(DevicePathToDriveLetterPath(
745       actual_device_path.Append(kRelativePath),
746       &win32_path));
747   EXPECT_EQ(FilePath(real_drive_letter + FILE_PATH_LITERAL("\\"))
748                 .Append(kRelativePath)
749                 .value(),
750             win32_path.value());
751 
752   // Deform the real path so that it is invalid by removing the last four
753   // characters.  The way windows names devices that are hard disks
754   // (\Device\HardDiskVolume${NUMBER}) guarantees that the string is longer
755   // than three characters.  The only way the truncated string could be a
756   // real drive is if more than 10^3 disks are mounted:
757   // \Device\HardDiskVolume10000 would be truncated to \Device\HardDiskVolume1
758   // Check that DevicePathToDriveLetterPath fails.
759   size_t path_length = actual_device_path.value().length();
760   size_t new_length = path_length - 4;
761   ASSERT_GT(new_length, 0u);
762   FilePath prefix_of_real_device_path(
763       actual_device_path.value().substr(0, new_length));
764   ASSERT_FALSE(DevicePathToDriveLetterPath(prefix_of_real_device_path,
765                                            &win32_path));
766 
767   ASSERT_FALSE(DevicePathToDriveLetterPath(
768       prefix_of_real_device_path.Append(kRelativePath),
769       &win32_path));
770 
771   // Deform the real path so that it is invalid by adding some characters. For
772   // example, if C: maps to \Device\HardDiskVolume8, then we simulate a
773   // request for the drive letter whose native path is
774   // \Device\HardDiskVolume812345 .  We assume such a device does not exist,
775   // because drives are numbered in order and mounting 112345 hard disks will
776   // never happen.
777   const FilePath::StringType kExtraChars = FPL("12345");
778 
779   FilePath real_device_path_plus_numbers(
780       actual_device_path.value() + kExtraChars);
781 
782   ASSERT_FALSE(DevicePathToDriveLetterPath(
783       real_device_path_plus_numbers,
784       &win32_path));
785 
786   ASSERT_FALSE(DevicePathToDriveLetterPath(
787       real_device_path_plus_numbers.Append(kRelativePath),
788       &win32_path));
789 }
790 
TEST_F(FileUtilTest,CreateTemporaryFileInDirLongPathTest)791 TEST_F(FileUtilTest, CreateTemporaryFileInDirLongPathTest) {
792   // Test that CreateTemporaryFileInDir() creates a path and returns a long path
793   // if it is available. This test requires that:
794   // - the filesystem at |temp_dir_| supports long filenames.
795   // - the account has FILE_LIST_DIRECTORY permission for all ancestor
796   //   directories of |temp_dir_|.
797   constexpr FilePath::CharType kLongDirName[] = FPL("A long path");
798   constexpr FilePath::CharType kTestSubDirName[] = FPL("test");
799   FilePath long_test_dir = temp_dir_.GetPath().Append(kLongDirName);
800   ASSERT_TRUE(CreateDirectory(long_test_dir));
801 
802   // kLongDirName is not a 8.3 component. So ::GetShortPathName() should give us
803   // a different short name.
804   FilePath short_test_dir = MakeShortFilePath(long_test_dir);
805   ASSERT_FALSE(short_test_dir.empty());
806   ASSERT_NE(kLongDirName, short_test_dir.BaseName().value());
807 
808   FilePath temp_file;
809   ASSERT_TRUE(CreateTemporaryFileInDir(short_test_dir, &temp_file));
810   EXPECT_EQ(kLongDirName, temp_file.DirName().BaseName().value());
811   EXPECT_TRUE(PathExists(temp_file));
812 
813   // Create a subdirectory of |long_test_dir| and make |long_test_dir|
814   // unreadable. We should still be able to create a temp file in the
815   // subdirectory, but we won't be able to determine the long path for it. This
816   // mimics the environment that some users run where their user profiles reside
817   // in a location where the don't have full access to the higher level
818   // directories. (Note that this assumption is true for NTFS, but not for some
819   // network file systems. E.g. AFS).
820   FilePath access_test_dir = long_test_dir.Append(kTestSubDirName);
821   ASSERT_TRUE(CreateDirectory(access_test_dir));
822   FilePermissionRestorer long_test_dir_restorer(long_test_dir);
823   ASSERT_TRUE(MakeFileUnreadable(long_test_dir));
824 
825   // Use the short form of the directory to create a temporary filename.
826   ASSERT_TRUE(CreateTemporaryFileInDir(
827       short_test_dir.Append(kTestSubDirName), &temp_file));
828   EXPECT_TRUE(PathExists(temp_file));
829   EXPECT_TRUE(short_test_dir.IsParent(temp_file.DirName()));
830 
831   // Check that the long path can't be determined for |temp_file|.
832   // Helper method base::MakeLongFilePath returns an empty path on error.
833   FilePath temp_file_long = MakeLongFilePath(temp_file);
834   ASSERT_TRUE(temp_file_long.empty());
835 }
836 
TEST_F(FileUtilTest,MakeLongFilePathTest)837 TEST_F(FileUtilTest, MakeLongFilePathTest) {
838   // Tests helper function base::MakeLongFilePath
839 
840   // If a username isn't a valid 8.3 short file name (even just a
841   // lengthy name like "user with long name"), Windows will set the TMP and TEMP
842   // environment variables to be 8.3 paths. ::GetTempPath (called in
843   // base::GetTempDir) just uses the value specified by TMP or TEMP, and so can
844   // return a short path. So from the start need to use MakeLongFilePath
845   // to normalize the path for such test environments.
846   FilePath temp_dir_long = MakeLongFilePath(temp_dir_.GetPath());
847   ASSERT_FALSE(temp_dir_long.empty());
848 
849   FilePath long_test_dir = temp_dir_long.Append(FPL("A long directory name"));
850   ASSERT_TRUE(CreateDirectory(long_test_dir));
851 
852   // Directory name is not a 8.3 component. So ::GetShortPathName() should give
853   // us a different short name.
854   FilePath short_test_dir = MakeShortFilePath(long_test_dir);
855   ASSERT_FALSE(short_test_dir.empty());
856 
857   EXPECT_NE(long_test_dir, short_test_dir);
858   EXPECT_EQ(long_test_dir, MakeLongFilePath(short_test_dir));
859 
860   FilePath long_test_file = long_test_dir.Append(FPL("A long file name.1234"));
861   CreateTextFile(long_test_file, bogus_content);
862   ASSERT_TRUE(PathExists(long_test_file));
863 
864   // File name is not a 8.3 component. So ::GetShortPathName() should give us
865   // a different short name.
866   FilePath short_test_file = MakeShortFilePath(long_test_file);
867   ASSERT_FALSE(short_test_file.empty());
868 
869   EXPECT_NE(long_test_file, short_test_file);
870   EXPECT_EQ(long_test_file, MakeLongFilePath(short_test_file));
871 
872   // MakeLongFilePath should return empty path if file does not exist.
873   EXPECT_TRUE(DeleteFile(short_test_file));
874   EXPECT_TRUE(MakeLongFilePath(short_test_file).empty());
875 
876   // MakeLongFilePath should return empty path if directory does not exist.
877   EXPECT_TRUE(DeleteFile(short_test_dir));
878   EXPECT_TRUE(MakeLongFilePath(short_test_dir).empty());
879 }
880 
TEST_F(FileUtilTest,CreateWinHardlinkTest)881 TEST_F(FileUtilTest, CreateWinHardlinkTest) {
882   // Link to a different file name in a sub-directory of |temp_dir_|.
883   FilePath test_dir = temp_dir_.GetPath().Append(FPL("test"));
884   ASSERT_TRUE(CreateDirectory(test_dir));
885   FilePath temp_file;
886   ASSERT_TRUE(CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file));
887   FilePath link_to_file = test_dir.Append(FPL("linked_name"));
888   EXPECT_TRUE(CreateWinHardLink(link_to_file, temp_file));
889   EXPECT_TRUE(PathExists(link_to_file));
890 
891   // Link two directories. This should fail. Verify that failure is returned
892   // by CreateWinHardLink.
893   EXPECT_FALSE(CreateWinHardLink(temp_dir_.GetPath(), test_dir));
894 }
895 
TEST_F(FileUtilTest,PreventExecuteMappingNewFile)896 TEST_F(FileUtilTest, PreventExecuteMappingNewFile) {
897   base::test::ScopedFeatureList enforcement_feature;
898   enforcement_feature.InitAndEnableFeature(
899       features::kEnforceNoExecutableFileHandles);
900   FilePath file = temp_dir_.GetPath().Append(FPL("afile.txt"));
901 
902   ASSERT_FALSE(PathExists(file));
903   {
904     File new_file(file, File::FLAG_WRITE | File::FLAG_WIN_NO_EXECUTE |
905                             File::FLAG_CREATE_ALWAYS);
906     ASSERT_TRUE(new_file.IsValid());
907   }
908 
909   {
910     File open_file(file, File::FLAG_READ | File::FLAG_WIN_EXECUTE |
911                              File::FLAG_OPEN_ALWAYS);
912     EXPECT_FALSE(open_file.IsValid());
913   }
914   // Verify the deny ACL did not prevent deleting the file.
915   EXPECT_TRUE(DeleteFile(file));
916 }
917 
TEST_F(FileUtilTest,PreventExecuteMappingExisting)918 TEST_F(FileUtilTest, PreventExecuteMappingExisting) {
919   base::test::ScopedFeatureList enforcement_feature;
920   enforcement_feature.InitAndEnableFeature(
921       features::kEnforceNoExecutableFileHandles);
922   FilePath file = temp_dir_.GetPath().Append(FPL("afile.txt"));
923   CreateTextFile(file, bogus_content);
924   ASSERT_TRUE(PathExists(file));
925   {
926     File open_file(file, File::FLAG_READ | File::FLAG_WIN_EXECUTE |
927                              File::FLAG_OPEN_ALWAYS);
928     EXPECT_TRUE(open_file.IsValid());
929   }
930   EXPECT_TRUE(PreventExecuteMapping(file));
931   {
932     File open_file(file, File::FLAG_READ | File::FLAG_WIN_EXECUTE |
933                              File::FLAG_OPEN_ALWAYS);
934     EXPECT_FALSE(open_file.IsValid());
935   }
936   // Verify the deny ACL did not prevent deleting the file.
937   EXPECT_TRUE(DeleteFile(file));
938 }
939 
TEST_F(FileUtilTest,PreventExecuteMappingOpenFile)940 TEST_F(FileUtilTest, PreventExecuteMappingOpenFile) {
941   base::test::ScopedFeatureList enforcement_feature;
942   enforcement_feature.InitAndEnableFeature(
943       features::kEnforceNoExecutableFileHandles);
944   FilePath file = temp_dir_.GetPath().Append(FPL("afile.txt"));
945   CreateTextFile(file, bogus_content);
946   ASSERT_TRUE(PathExists(file));
947   File open_file(file, File::FLAG_READ | File::FLAG_WRITE |
948                            File::FLAG_WIN_EXECUTE | File::FLAG_OPEN_ALWAYS);
949   EXPECT_TRUE(open_file.IsValid());
950   // Verify ACE can be set even on an open file.
951   EXPECT_TRUE(PreventExecuteMapping(file));
952   {
953     File second_open_file(
954         file, File::FLAG_READ | File::FLAG_WRITE | File::FLAG_OPEN_ALWAYS);
955     EXPECT_TRUE(second_open_file.IsValid());
956   }
957   {
958     File third_open_file(file, File::FLAG_READ | File::FLAG_WIN_EXECUTE |
959                                    File::FLAG_OPEN_ALWAYS);
960     EXPECT_FALSE(third_open_file.IsValid());
961   }
962 
963   open_file.Close();
964   // Verify the deny ACL did not prevent deleting the file.
965   EXPECT_TRUE(DeleteFile(file));
966 }
967 
TEST(FileUtilDeathTest,DisallowNoExecuteOnUnsafeFile)968 TEST(FileUtilDeathTest, DisallowNoExecuteOnUnsafeFile) {
969   base::test::ScopedFeatureList enforcement_feature;
970   enforcement_feature.InitAndEnableFeature(
971       features::kEnforceNoExecutableFileHandles);
972   base::FilePath local_app_data;
973   // This test places a file in %LOCALAPPDATA% to verify that the checks in
974   // IsPathSafeToSetAclOn work correctly.
975   ASSERT_TRUE(
976       base::PathService::Get(base::DIR_LOCAL_APP_DATA, &local_app_data));
977 
978   base::FilePath file_path;
979   EXPECT_DCHECK_DEATH_WITH(
980       {
981         {
982           base::File temp_file =
983               base::CreateAndOpenTemporaryFileInDir(local_app_data, &file_path);
984         }
985         File reopen_file(file_path, File::FLAG_READ | File::FLAG_WRITE |
986                                         File::FLAG_WIN_NO_EXECUTE |
987                                         File::FLAG_OPEN_ALWAYS |
988                                         File::FLAG_DELETE_ON_CLOSE);
989       },
990       "Unsafe to deny execute access to path");
991 }
992 
MULTIPROCESS_TEST_MAIN(NoExecuteOnSafeFileMain)993 MULTIPROCESS_TEST_MAIN(NoExecuteOnSafeFileMain) {
994   base::FilePath temp_file;
995   CHECK(base::CreateTemporaryFile(&temp_file));
996 
997   // A file with FLAG_WIN_NO_EXECUTE created in temp dir should always be
998   // permitted.
999   File reopen_file(temp_file, File::FLAG_READ | File::FLAG_WRITE |
1000                                   File::FLAG_WIN_NO_EXECUTE |
1001                                   File::FLAG_OPEN_ALWAYS |
1002                                   File::FLAG_DELETE_ON_CLOSE);
1003   return 0;
1004 }
1005 
TEST_F(FileUtilTest,NoExecuteOnSafeFile)1006 TEST_F(FileUtilTest, NoExecuteOnSafeFile) {
1007   FilePath new_dir;
1008   ASSERT_TRUE(CreateTemporaryDirInDir(
1009       temp_dir_.GetPath(), FILE_PATH_LITERAL("NoExecuteOnSafeFileLongPath"),
1010       &new_dir));
1011 
1012   FilePath short_dir = base::MakeShortFilePath(new_dir);
1013 
1014   // Verify that the path really is 8.3 now.
1015   ASSERT_NE(new_dir.value(), short_dir.value());
1016 
1017   LaunchOptions options;
1018   options.environment[L"TMP"] = short_dir.value();
1019 
1020   CommandLine child_command_line(GetMultiProcessTestChildBaseCommandLine());
1021 
1022   Process child_process = SpawnMultiProcessTestChild(
1023       "NoExecuteOnSafeFileMain", child_command_line, options);
1024   ASSERT_TRUE(child_process.IsValid());
1025   int rv = -1;
1026   ASSERT_TRUE(WaitForMultiprocessTestChildExit(
1027       child_process, TestTimeouts::action_timeout(), &rv));
1028   ASSERT_EQ(0, rv);
1029 }
1030 
1031 class FileUtilExecuteEnforcementTest
1032     : public FileUtilTest,
1033       public ::testing::WithParamInterface<bool> {
1034  public:
FileUtilExecuteEnforcementTest()1035   FileUtilExecuteEnforcementTest() {
1036     if (IsEnforcementEnabled()) {
1037       enforcement_feature_.InitAndEnableFeature(
1038           features::kEnforceNoExecutableFileHandles);
1039     } else {
1040       enforcement_feature_.InitAndDisableFeature(
1041           features::kEnforceNoExecutableFileHandles);
1042     }
1043   }
1044 
1045  protected:
IsEnforcementEnabled()1046   bool IsEnforcementEnabled() { return GetParam(); }
1047 
1048  private:
1049   base::test::ScopedFeatureList enforcement_feature_;
1050 };
1051 
1052 // This test verifies that if a file has been passed to `PreventExecuteMapping`
1053 // and enforcement is enabled, then it cannot be mapped as executable into
1054 // memory.
TEST_P(FileUtilExecuteEnforcementTest,Functional)1055 TEST_P(FileUtilExecuteEnforcementTest, Functional) {
1056   FilePath dir_exe;
1057   EXPECT_TRUE(PathService::Get(DIR_EXE, &dir_exe));
1058   // This DLL is built as part of base_unittests so is guaranteed to be present.
1059   FilePath test_dll(dir_exe.Append(FPL("scoped_handle_test_dll.dll")));
1060 
1061   EXPECT_TRUE(base::PathExists(test_dll));
1062 
1063   FilePath dll_copy_path = temp_dir_.GetPath().Append(FPL("test.dll"));
1064 
1065   ASSERT_TRUE(CopyFile(test_dll, dll_copy_path));
1066   ASSERT_TRUE(PreventExecuteMapping(dll_copy_path));
1067   ScopedNativeLibrary module(dll_copy_path);
1068 
1069   // If enforcement is enabled, then `PreventExecuteMapping` will have prevented
1070   // the load, and the module will be invalid.
1071   EXPECT_EQ(IsEnforcementEnabled(), !module.is_valid());
1072 }
1073 
1074 INSTANTIATE_TEST_SUITE_P(EnforcementEnabled,
1075                          FileUtilExecuteEnforcementTest,
1076                          ::testing::Values(true));
1077 INSTANTIATE_TEST_SUITE_P(EnforcementDisabled,
1078                          FileUtilExecuteEnforcementTest,
1079                          ::testing::Values(false));
1080 
1081 #endif  // BUILDFLAG(IS_WIN)
1082 
1083 #if BUILDFLAG(IS_POSIX)
1084 
TEST_F(FileUtilTest,CreateAndReadSymlinks)1085 TEST_F(FileUtilTest, CreateAndReadSymlinks) {
1086   FilePath link_from = temp_dir_.GetPath().Append(FPL("from_file"));
1087   FilePath link_to = temp_dir_.GetPath().Append(FPL("to_file"));
1088   CreateTextFile(link_to, bogus_content);
1089 
1090   ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
1091     << "Failed to create file symlink.";
1092 
1093   // If we created the link properly, we should be able to read the contents
1094   // through it.
1095   EXPECT_EQ(bogus_content, ReadTextFile(link_from));
1096 
1097   FilePath result;
1098   ASSERT_TRUE(ReadSymbolicLink(link_from, &result));
1099   EXPECT_EQ(link_to.value(), result.value());
1100 
1101   // Link to a directory.
1102   link_from = temp_dir_.GetPath().Append(FPL("from_dir"));
1103   link_to = temp_dir_.GetPath().Append(FPL("to_dir"));
1104   ASSERT_TRUE(CreateDirectory(link_to));
1105   ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
1106     << "Failed to create directory symlink.";
1107 
1108   // Test failures.
1109   EXPECT_FALSE(CreateSymbolicLink(link_to, link_to));
1110   EXPECT_FALSE(ReadSymbolicLink(link_to, &result));
1111   FilePath missing = temp_dir_.GetPath().Append(FPL("missing"));
1112   EXPECT_FALSE(ReadSymbolicLink(missing, &result));
1113 }
1114 
TEST_F(FileUtilTest,CreateAndReadRelativeSymlinks)1115 TEST_F(FileUtilTest, CreateAndReadRelativeSymlinks) {
1116   FilePath link_from = temp_dir_.GetPath().Append(FPL("from_file"));
1117   FilePath filename_link_to("to_file");
1118   FilePath link_to = temp_dir_.GetPath().Append(filename_link_to);
1119   FilePath link_from_in_subdir =
1120       temp_dir_.GetPath().Append(FPL("subdir")).Append(FPL("from_file"));
1121   FilePath link_to_in_subdir = FilePath(FPL("..")).Append(filename_link_to);
1122   CreateTextFile(link_to, bogus_content);
1123 
1124   ASSERT_TRUE(CreateDirectory(link_from_in_subdir.DirName()));
1125   ASSERT_TRUE(CreateSymbolicLink(link_to_in_subdir, link_from_in_subdir));
1126 
1127   ASSERT_TRUE(CreateSymbolicLink(filename_link_to, link_from))
1128       << "Failed to create file symlink.";
1129 
1130   // If we created the link properly, we should be able to read the contents
1131   // through it.
1132   EXPECT_EQ(bogus_content, ReadTextFile(link_from));
1133   EXPECT_EQ(bogus_content, ReadTextFile(link_from_in_subdir));
1134 
1135   FilePath result;
1136   ASSERT_TRUE(ReadSymbolicLink(link_from, &result));
1137   EXPECT_EQ(filename_link_to.value(), result.value());
1138 
1139   std::optional<FilePath> absolute_link = ReadSymbolicLinkAbsolute(link_from);
1140   ASSERT_TRUE(absolute_link);
1141   EXPECT_EQ(link_to.value(), absolute_link->value());
1142 
1143   absolute_link = ReadSymbolicLinkAbsolute(link_from_in_subdir);
1144   ASSERT_TRUE(absolute_link);
1145   EXPECT_EQ(link_to.value(), absolute_link->value());
1146 
1147   // Link to a directory.
1148   link_from = temp_dir_.GetPath().Append(FPL("from_dir"));
1149   filename_link_to = FilePath("to_dir");
1150   link_to = temp_dir_.GetPath().Append(filename_link_to);
1151   ASSERT_TRUE(CreateDirectory(link_to));
1152   ASSERT_TRUE(CreateSymbolicLink(filename_link_to, link_from))
1153       << "Failed to create relative directory symlink.";
1154 
1155   ASSERT_TRUE(ReadSymbolicLink(link_from, &result));
1156   EXPECT_EQ(filename_link_to.value(), result.value());
1157 
1158   absolute_link = ReadSymbolicLinkAbsolute(link_from);
1159   ASSERT_TRUE(absolute_link);
1160   EXPECT_EQ(link_to.value(), absolute_link->value());
1161 
1162   // Test failures.
1163   EXPECT_FALSE(CreateSymbolicLink(link_to, link_to));
1164   EXPECT_FALSE(ReadSymbolicLink(link_to, &result));
1165 }
1166 
1167 // The following test of NormalizeFilePath() require that we create a symlink.
1168 // This can not be done on Windows before Vista.  On Vista, creating a symlink
1169 // requires privilege "SeCreateSymbolicLinkPrivilege".
1170 // TODO(skerner): Investigate the possibility of giving base_unittests the
1171 // privileges required to create a symlink.
TEST_F(FileUtilTest,NormalizeFilePathSymlinks)1172 TEST_F(FileUtilTest, NormalizeFilePathSymlinks) {
1173   // Link one file to another.
1174   FilePath link_from = temp_dir_.GetPath().Append(FPL("from_file"));
1175   FilePath link_to = temp_dir_.GetPath().Append(FPL("to_file"));
1176   CreateTextFile(link_to, bogus_content);
1177 
1178   ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
1179     << "Failed to create file symlink.";
1180 
1181   // Check that NormalizeFilePath sees the link.
1182   FilePath normalized_path;
1183   ASSERT_TRUE(NormalizeFilePath(link_from, &normalized_path));
1184   EXPECT_NE(link_from, link_to);
1185   EXPECT_EQ(link_to.BaseName().value(), normalized_path.BaseName().value());
1186   EXPECT_EQ(link_to.BaseName().value(), normalized_path.BaseName().value());
1187 
1188   // Link to a directory.
1189   link_from = temp_dir_.GetPath().Append(FPL("from_dir"));
1190   link_to = temp_dir_.GetPath().Append(FPL("to_dir"));
1191   ASSERT_TRUE(CreateDirectory(link_to));
1192   ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
1193     << "Failed to create directory symlink.";
1194 
1195   EXPECT_FALSE(NormalizeFilePath(link_from, &normalized_path))
1196     << "Links to directories should return false.";
1197 
1198   // Test that a loop in the links causes NormalizeFilePath() to return false.
1199   link_from = temp_dir_.GetPath().Append(FPL("link_a"));
1200   link_to = temp_dir_.GetPath().Append(FPL("link_b"));
1201   ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
1202     << "Failed to create loop symlink a.";
1203   ASSERT_TRUE(CreateSymbolicLink(link_from, link_to))
1204     << "Failed to create loop symlink b.";
1205 
1206   // Infinite loop!
1207   EXPECT_FALSE(NormalizeFilePath(link_from, &normalized_path));
1208 }
1209 
TEST_F(FileUtilTest,DeleteSymlinkToExistentFile)1210 TEST_F(FileUtilTest, DeleteSymlinkToExistentFile) {
1211   // Create a file.
1212   FilePath file_name = temp_dir_.GetPath().Append(FPL("Test DeleteFile 2.txt"));
1213   CreateTextFile(file_name, bogus_content);
1214   ASSERT_TRUE(PathExists(file_name));
1215 
1216   // Create a symlink to the file.
1217   FilePath file_link = temp_dir_.GetPath().Append("file_link_2");
1218   ASSERT_TRUE(CreateSymbolicLink(file_name, file_link))
1219       << "Failed to create symlink.";
1220 
1221   // Delete the symbolic link.
1222   EXPECT_TRUE(DeleteFile(file_link));
1223 
1224   // Make sure original file is not deleted.
1225   EXPECT_FALSE(PathExists(file_link));
1226   EXPECT_TRUE(PathExists(file_name));
1227 }
1228 
TEST_F(FileUtilTest,DeleteSymlinkToNonExistentFile)1229 TEST_F(FileUtilTest, DeleteSymlinkToNonExistentFile) {
1230   // Create a non-existent file path.
1231   FilePath non_existent =
1232       temp_dir_.GetPath().Append(FPL("Test DeleteFile 3.txt"));
1233   EXPECT_FALSE(PathExists(non_existent));
1234 
1235   // Create a symlink to the non-existent file.
1236   FilePath file_link = temp_dir_.GetPath().Append("file_link_3");
1237   ASSERT_TRUE(CreateSymbolicLink(non_existent, file_link))
1238       << "Failed to create symlink.";
1239 
1240   // Make sure the symbolic link is exist.
1241   EXPECT_TRUE(IsLink(file_link));
1242   EXPECT_FALSE(PathExists(file_link));
1243 
1244   // Delete the symbolic link.
1245   EXPECT_TRUE(DeleteFile(file_link));
1246 
1247   // Make sure the symbolic link is deleted.
1248   EXPECT_FALSE(IsLink(file_link));
1249 }
1250 
TEST_F(FileUtilTest,CopyFileFollowsSymlinks)1251 TEST_F(FileUtilTest, CopyFileFollowsSymlinks) {
1252   FilePath link_from = temp_dir_.GetPath().Append(FPL("from_file"));
1253   FilePath link_to = temp_dir_.GetPath().Append(FPL("to_file"));
1254   CreateTextFile(link_to, bogus_content);
1255 
1256   ASSERT_TRUE(CreateSymbolicLink(link_to, link_from));
1257 
1258   // If we created the link properly, we should be able to read the contents
1259   // through it.
1260   EXPECT_EQ(bogus_content, ReadTextFile(link_from));
1261 
1262   FilePath result;
1263   ASSERT_TRUE(ReadSymbolicLink(link_from, &result));
1264   EXPECT_EQ(link_to.value(), result.value());
1265 
1266   // Create another file and copy it to |link_from|.
1267   FilePath src_file = temp_dir_.GetPath().Append(FPL("src.txt"));
1268   const std::wstring file_contents(L"Gooooooooooooooooooooogle");
1269   CreateTextFile(src_file, file_contents);
1270   ASSERT_TRUE(CopyFile(src_file, link_from));
1271 
1272   // Make sure |link_from| is still a symlink, and |link_to| has been written to
1273   // by CopyFile().
1274   EXPECT_TRUE(IsLink(link_from));
1275   EXPECT_EQ(file_contents, ReadTextFile(link_from));
1276   EXPECT_EQ(file_contents, ReadTextFile(link_to));
1277 }
1278 
TEST_F(FileUtilTest,ChangeFilePermissionsAndRead)1279 TEST_F(FileUtilTest, ChangeFilePermissionsAndRead) {
1280   // Create a file path.
1281   FilePath file_name =
1282       temp_dir_.GetPath().Append(FPL("Test Readable File.txt"));
1283   EXPECT_FALSE(PathExists(file_name));
1284   EXPECT_FALSE(PathIsReadable(file_name));
1285 
1286   static constexpr char kData[] = "hello";
1287   static constexpr int kDataSize = sizeof(kData) - 1;
1288   char buffer[kDataSize];
1289 
1290   // Write file.
1291   EXPECT_TRUE(WriteFile(file_name, kData));
1292   EXPECT_TRUE(PathExists(file_name));
1293 
1294   // Make sure the file is readable.
1295   int32_t mode = 0;
1296   EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
1297   EXPECT_TRUE(mode & FILE_PERMISSION_READ_BY_USER);
1298   EXPECT_TRUE(PathIsReadable(file_name));
1299 
1300   // Get rid of the read permission.
1301   EXPECT_TRUE(SetPosixFilePermissions(file_name, 0u));
1302   EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
1303   EXPECT_FALSE(mode & FILE_PERMISSION_READ_BY_USER);
1304   EXPECT_FALSE(PathIsReadable(file_name));
1305   // Make sure the file can't be read.
1306   EXPECT_EQ(ReadFile(file_name, buffer), std::nullopt);
1307 
1308   // Give the read permission.
1309   EXPECT_TRUE(SetPosixFilePermissions(file_name, FILE_PERMISSION_READ_BY_USER));
1310   EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
1311   EXPECT_TRUE(mode & FILE_PERMISSION_READ_BY_USER);
1312   EXPECT_TRUE(PathIsReadable(file_name));
1313   // Make sure the file can be read.
1314   EXPECT_EQ(ReadFile(file_name, buffer), kDataSize);
1315 
1316   // Delete the file.
1317   EXPECT_TRUE(DeleteFile(file_name));
1318   EXPECT_FALSE(PathExists(file_name));
1319 }
1320 
TEST_F(FileUtilTest,ChangeFilePermissionsAndWrite)1321 TEST_F(FileUtilTest, ChangeFilePermissionsAndWrite) {
1322   // Create a file path.
1323   FilePath file_name =
1324       temp_dir_.GetPath().Append(FPL("Test Readable File.txt"));
1325   EXPECT_FALSE(PathExists(file_name));
1326 
1327   const std::string kData("hello");
1328 
1329   // Write file.
1330   EXPECT_TRUE(WriteFile(file_name, kData));
1331   EXPECT_TRUE(PathExists(file_name));
1332 
1333   // Make sure the file is writable.
1334   int mode = 0;
1335   EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
1336   EXPECT_TRUE(mode & FILE_PERMISSION_WRITE_BY_USER);
1337   EXPECT_TRUE(PathIsWritable(file_name));
1338 
1339   // Get rid of the write permission.
1340   EXPECT_TRUE(SetPosixFilePermissions(file_name, 0u));
1341   EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
1342   EXPECT_FALSE(mode & FILE_PERMISSION_WRITE_BY_USER);
1343   // Make sure the file can't be write.
1344   EXPECT_FALSE(WriteFile(file_name, kData));
1345   EXPECT_FALSE(PathIsWritable(file_name));
1346 
1347   // Give read permission.
1348   EXPECT_TRUE(SetPosixFilePermissions(file_name,
1349                                       FILE_PERMISSION_WRITE_BY_USER));
1350   EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
1351   EXPECT_TRUE(mode & FILE_PERMISSION_WRITE_BY_USER);
1352   // Make sure the file can be write.
1353   EXPECT_TRUE(WriteFile(file_name, kData));
1354   EXPECT_TRUE(PathIsWritable(file_name));
1355 
1356   // Delete the file.
1357   EXPECT_TRUE(DeleteFile(file_name));
1358   EXPECT_FALSE(PathExists(file_name));
1359 }
1360 
TEST_F(FileUtilTest,ChangeDirectoryPermissionsAndEnumerate)1361 TEST_F(FileUtilTest, ChangeDirectoryPermissionsAndEnumerate) {
1362   // Create a directory path.
1363   FilePath subdir_path = temp_dir_.GetPath().Append(FPL("PermissionTest1"));
1364   CreateDirectory(subdir_path);
1365   ASSERT_TRUE(PathExists(subdir_path));
1366 
1367   // Create a dummy file to enumerate.
1368   FilePath file_name = subdir_path.Append(FPL("Test Readable File.txt"));
1369   EXPECT_FALSE(PathExists(file_name));
1370   const std::string kData("hello");
1371   EXPECT_TRUE(WriteFile(file_name, kData));
1372   EXPECT_TRUE(PathExists(file_name));
1373 
1374   // Make sure the directory has the all permissions.
1375   int mode = 0;
1376   EXPECT_TRUE(GetPosixFilePermissions(subdir_path, &mode));
1377   EXPECT_EQ(FILE_PERMISSION_USER_MASK, mode & FILE_PERMISSION_USER_MASK);
1378 
1379   // Get rid of the permissions from the directory.
1380   EXPECT_TRUE(SetPosixFilePermissions(subdir_path, 0u));
1381   EXPECT_TRUE(GetPosixFilePermissions(subdir_path, &mode));
1382   EXPECT_FALSE(mode & FILE_PERMISSION_USER_MASK);
1383 
1384   // Make sure the file in the directory can't be enumerated.
1385   FileEnumerator f1(subdir_path, true, FileEnumerator::FILES);
1386   EXPECT_TRUE(PathExists(subdir_path));
1387   FindResultCollector c1(&f1);
1388   EXPECT_EQ(0, c1.size());
1389   EXPECT_FALSE(GetPosixFilePermissions(file_name, &mode));
1390 
1391   // Give the permissions to the directory.
1392   EXPECT_TRUE(SetPosixFilePermissions(subdir_path, FILE_PERMISSION_USER_MASK));
1393   EXPECT_TRUE(GetPosixFilePermissions(subdir_path, &mode));
1394   EXPECT_EQ(FILE_PERMISSION_USER_MASK, mode & FILE_PERMISSION_USER_MASK);
1395 
1396   // Make sure the file in the directory can be enumerated.
1397   FileEnumerator f2(subdir_path, true, FileEnumerator::FILES);
1398   FindResultCollector c2(&f2);
1399   EXPECT_TRUE(c2.HasFile(file_name));
1400   EXPECT_EQ(1, c2.size());
1401 
1402   // Delete the file.
1403   EXPECT_TRUE(DeletePathRecursively(subdir_path));
1404   EXPECT_FALSE(PathExists(subdir_path));
1405 }
1406 
TEST_F(FileUtilTest,ExecutableExistsInPath)1407 TEST_F(FileUtilTest, ExecutableExistsInPath) {
1408   // Create two directories that we will put in our PATH
1409   const FilePath::CharType kDir1[] = FPL("dir1");
1410   const FilePath::CharType kDir2[] = FPL("dir2");
1411 
1412   FilePath dir1 = temp_dir_.GetPath().Append(kDir1);
1413   FilePath dir2 = temp_dir_.GetPath().Append(kDir2);
1414   ASSERT_TRUE(CreateDirectory(dir1));
1415   ASSERT_TRUE(CreateDirectory(dir2));
1416 
1417   ScopedEnvironmentVariableOverride scoped_env(
1418       "PATH", dir1.value() + ":" + dir2.value());
1419   ASSERT_TRUE(scoped_env.IsOverridden());
1420 
1421   const FilePath::CharType kRegularFileName[] = FPL("regular_file");
1422   const FilePath::CharType kExeFileName[] = FPL("exe");
1423   const FilePath::CharType kDneFileName[] = FPL("does_not_exist");
1424 
1425   const FilePath kExePath = dir1.Append(kExeFileName);
1426   const FilePath kRegularFilePath = dir2.Append(kRegularFileName);
1427 
1428   // Write file.
1429   const std::string kData("hello");
1430   ASSERT_TRUE(WriteFile(kExePath, kData));
1431   ASSERT_TRUE(PathExists(kExePath));
1432   ASSERT_TRUE(WriteFile(kRegularFilePath, kData));
1433   ASSERT_TRUE(PathExists(kRegularFilePath));
1434 
1435   ASSERT_TRUE(SetPosixFilePermissions(dir1.Append(kExeFileName),
1436                                       FILE_PERMISSION_EXECUTE_BY_USER));
1437 
1438   EXPECT_TRUE(ExecutableExistsInPath(scoped_env.GetEnv(), kExeFileName));
1439   EXPECT_FALSE(ExecutableExistsInPath(scoped_env.GetEnv(), kRegularFileName));
1440   EXPECT_FALSE(ExecutableExistsInPath(scoped_env.GetEnv(), kDneFileName));
1441 }
1442 
TEST_F(FileUtilTest,CopyDirectoryPermissions)1443 TEST_F(FileUtilTest, CopyDirectoryPermissions) {
1444   // Create a directory.
1445   FilePath dir_name_from =
1446       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1447   CreateDirectory(dir_name_from);
1448   ASSERT_TRUE(PathExists(dir_name_from));
1449 
1450   // Create some regular files under the directory with various permissions.
1451   FilePath file_name_from =
1452       dir_name_from.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
1453   CreateTextFile(file_name_from, L"Mordecai");
1454   ASSERT_TRUE(PathExists(file_name_from));
1455   ASSERT_TRUE(SetPosixFilePermissions(file_name_from, 0755));
1456 
1457   FilePath file2_name_from =
1458       dir_name_from.Append(FILE_PATH_LITERAL("Reggy-2.txt"));
1459   CreateTextFile(file2_name_from, L"Rigby");
1460   ASSERT_TRUE(PathExists(file2_name_from));
1461   ASSERT_TRUE(SetPosixFilePermissions(file2_name_from, 0777));
1462 
1463   FilePath file3_name_from =
1464       dir_name_from.Append(FILE_PATH_LITERAL("Reggy-3.txt"));
1465   CreateTextFile(file3_name_from, L"Benson");
1466   ASSERT_TRUE(PathExists(file3_name_from));
1467   ASSERT_TRUE(SetPosixFilePermissions(file3_name_from, 0400));
1468 
1469   // Copy the directory recursively.
1470   FilePath dir_name_to =
1471       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1472   FilePath file_name_to =
1473       dir_name_to.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
1474   FilePath file2_name_to =
1475       dir_name_to.Append(FILE_PATH_LITERAL("Reggy-2.txt"));
1476   FilePath file3_name_to =
1477       dir_name_to.Append(FILE_PATH_LITERAL("Reggy-3.txt"));
1478 
1479   ASSERT_FALSE(PathExists(dir_name_to));
1480 
1481   EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, true));
1482   ASSERT_TRUE(PathExists(file_name_to));
1483   ASSERT_TRUE(PathExists(file2_name_to));
1484   ASSERT_TRUE(PathExists(file3_name_to));
1485 
1486   int mode = 0;
1487   int expected_mode;
1488   ASSERT_TRUE(GetPosixFilePermissions(file_name_to, &mode));
1489 #if BUILDFLAG(IS_APPLE)
1490   expected_mode = 0755;
1491 #elif BUILDFLAG(IS_CHROMEOS)
1492   expected_mode = 0644;
1493 #else
1494   expected_mode = 0600;
1495 #endif
1496   EXPECT_EQ(expected_mode, mode);
1497 
1498   ASSERT_TRUE(GetPosixFilePermissions(file2_name_to, &mode));
1499 #if BUILDFLAG(IS_APPLE)
1500   expected_mode = 0755;
1501 #elif BUILDFLAG(IS_CHROMEOS)
1502   expected_mode = 0644;
1503 #else
1504   expected_mode = 0600;
1505 #endif
1506   EXPECT_EQ(expected_mode, mode);
1507 
1508   ASSERT_TRUE(GetPosixFilePermissions(file3_name_to, &mode));
1509 #if BUILDFLAG(IS_APPLE)
1510   expected_mode = 0600;
1511 #elif BUILDFLAG(IS_CHROMEOS)
1512   expected_mode = 0644;
1513 #else
1514   expected_mode = 0600;
1515 #endif
1516   EXPECT_EQ(expected_mode, mode);
1517 }
1518 
TEST_F(FileUtilTest,CopyDirectoryPermissionsOverExistingFile)1519 TEST_F(FileUtilTest, CopyDirectoryPermissionsOverExistingFile) {
1520   // Create a directory.
1521   FilePath dir_name_from =
1522       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1523   CreateDirectory(dir_name_from);
1524   ASSERT_TRUE(PathExists(dir_name_from));
1525 
1526   // Create a file under the directory.
1527   FilePath file_name_from =
1528       dir_name_from.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
1529   CreateTextFile(file_name_from, L"Mordecai");
1530   ASSERT_TRUE(PathExists(file_name_from));
1531   ASSERT_TRUE(SetPosixFilePermissions(file_name_from, 0644));
1532 
1533   // Create a directory.
1534   FilePath dir_name_to =
1535       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1536   CreateDirectory(dir_name_to);
1537   ASSERT_TRUE(PathExists(dir_name_to));
1538 
1539   // Create a file under the directory with wider permissions.
1540   FilePath file_name_to =
1541       dir_name_to.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
1542   CreateTextFile(file_name_to, L"Rigby");
1543   ASSERT_TRUE(PathExists(file_name_to));
1544   ASSERT_TRUE(SetPosixFilePermissions(file_name_to, 0777));
1545 
1546   // Ensure that when we copy the directory, the file contents are copied
1547   // but the permissions on the destination are left alone.
1548   EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
1549   ASSERT_TRUE(PathExists(file_name_to));
1550   ASSERT_EQ(L"Mordecai", ReadTextFile(file_name_to));
1551 
1552   int mode = 0;
1553   ASSERT_TRUE(GetPosixFilePermissions(file_name_to, &mode));
1554   EXPECT_EQ(0777, mode);
1555 }
1556 
TEST_F(FileUtilTest,CopyDirectoryExclDoesNotOverwrite)1557 TEST_F(FileUtilTest, CopyDirectoryExclDoesNotOverwrite) {
1558   // Create source directory.
1559   FilePath dir_name_from =
1560       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1561   CreateDirectory(dir_name_from);
1562   ASSERT_TRUE(PathExists(dir_name_from));
1563 
1564   // Create a file under the directory.
1565   FilePath file_name_from =
1566       dir_name_from.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
1567   CreateTextFile(file_name_from, L"Mordecai");
1568   ASSERT_TRUE(PathExists(file_name_from));
1569 
1570   // Create destination directory.
1571   FilePath dir_name_to =
1572       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1573   CreateDirectory(dir_name_to);
1574   ASSERT_TRUE(PathExists(dir_name_to));
1575 
1576   // Create a file under the directory with the same name.
1577   FilePath file_name_to = dir_name_to.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
1578   CreateTextFile(file_name_to, L"Rigby");
1579   ASSERT_TRUE(PathExists(file_name_to));
1580 
1581   // Ensure that copying failed and the file was not overwritten.
1582   EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
1583   ASSERT_TRUE(PathExists(file_name_to));
1584   ASSERT_EQ(L"Rigby", ReadTextFile(file_name_to));
1585 }
1586 
TEST_F(FileUtilTest,CopyDirectoryExclDirectoryOverExistingFile)1587 TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverExistingFile) {
1588   // Create source directory.
1589   FilePath dir_name_from =
1590       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1591   CreateDirectory(dir_name_from);
1592   ASSERT_TRUE(PathExists(dir_name_from));
1593 
1594   // Create a subdirectory.
1595   FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub"));
1596   CreateDirectory(subdir_name_from);
1597   ASSERT_TRUE(PathExists(subdir_name_from));
1598 
1599   // Create destination directory.
1600   FilePath dir_name_to =
1601       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1602   CreateDirectory(dir_name_to);
1603   ASSERT_TRUE(PathExists(dir_name_to));
1604 
1605   // Create a regular file under the directory with the same name.
1606   FilePath file_name_to = dir_name_to.Append(FILE_PATH_LITERAL("Subsub"));
1607   CreateTextFile(file_name_to, L"Rigby");
1608   ASSERT_TRUE(PathExists(file_name_to));
1609 
1610   // Ensure that copying failed and the file was not overwritten.
1611   EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
1612   ASSERT_TRUE(PathExists(file_name_to));
1613   ASSERT_EQ(L"Rigby", ReadTextFile(file_name_to));
1614 }
1615 
TEST_F(FileUtilTest,CopyDirectoryExclDirectoryOverExistingDirectory)1616 TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverExistingDirectory) {
1617   // Create source directory.
1618   FilePath dir_name_from =
1619       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1620   CreateDirectory(dir_name_from);
1621   ASSERT_TRUE(PathExists(dir_name_from));
1622 
1623   // Create a subdirectory.
1624   FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub"));
1625   CreateDirectory(subdir_name_from);
1626   ASSERT_TRUE(PathExists(subdir_name_from));
1627 
1628   // Create destination directory.
1629   FilePath dir_name_to =
1630       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1631   CreateDirectory(dir_name_to);
1632   ASSERT_TRUE(PathExists(dir_name_to));
1633 
1634   // Create a subdirectory under the directory with the same name.
1635   FilePath subdir_name_to = dir_name_to.Append(FILE_PATH_LITERAL("Subsub"));
1636   CreateDirectory(subdir_name_to);
1637   ASSERT_TRUE(PathExists(subdir_name_to));
1638 
1639   // Ensure that copying failed and the file was not overwritten.
1640   EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
1641 }
1642 
TEST_F(FileUtilTest,CopyFileExecutablePermission)1643 TEST_F(FileUtilTest, CopyFileExecutablePermission) {
1644   FilePath src = temp_dir_.GetPath().Append(FPL("src.txt"));
1645   const std::wstring file_contents(L"Gooooooooooooooooooooogle");
1646   CreateTextFile(src, file_contents);
1647 
1648   ASSERT_TRUE(SetPosixFilePermissions(src, 0755));
1649   int mode = 0;
1650   ASSERT_TRUE(GetPosixFilePermissions(src, &mode));
1651   EXPECT_EQ(0755, mode);
1652 
1653   FilePath dst = temp_dir_.GetPath().Append(FPL("dst.txt"));
1654   ASSERT_TRUE(CopyFile(src, dst));
1655   EXPECT_EQ(file_contents, ReadTextFile(dst));
1656 
1657   ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
1658   int expected_mode;
1659 #if BUILDFLAG(IS_APPLE)
1660   expected_mode = 0755;
1661 #elif BUILDFLAG(IS_CHROMEOS)
1662   expected_mode = 0644;
1663 #else
1664   expected_mode = 0600;
1665 #endif
1666   EXPECT_EQ(expected_mode, mode);
1667   ASSERT_TRUE(DeleteFile(dst));
1668 
1669   ASSERT_TRUE(SetPosixFilePermissions(src, 0777));
1670   ASSERT_TRUE(GetPosixFilePermissions(src, &mode));
1671   EXPECT_EQ(0777, mode);
1672 
1673   ASSERT_TRUE(CopyFile(src, dst));
1674   EXPECT_EQ(file_contents, ReadTextFile(dst));
1675 
1676   ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
1677 #if BUILDFLAG(IS_APPLE)
1678   expected_mode = 0755;
1679 #elif BUILDFLAG(IS_CHROMEOS)
1680   expected_mode = 0644;
1681 #else
1682   expected_mode = 0600;
1683 #endif
1684   EXPECT_EQ(expected_mode, mode);
1685   ASSERT_TRUE(DeleteFile(dst));
1686 
1687   ASSERT_TRUE(SetPosixFilePermissions(src, 0400));
1688   ASSERT_TRUE(GetPosixFilePermissions(src, &mode));
1689   EXPECT_EQ(0400, mode);
1690 
1691   ASSERT_TRUE(CopyFile(src, dst));
1692   EXPECT_EQ(file_contents, ReadTextFile(dst));
1693 
1694   ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
1695 #if BUILDFLAG(IS_APPLE)
1696   expected_mode = 0600;
1697 #elif BUILDFLAG(IS_CHROMEOS)
1698   expected_mode = 0644;
1699 #else
1700   expected_mode = 0600;
1701 #endif
1702   EXPECT_EQ(expected_mode, mode);
1703 
1704   // This time, do not delete |dst|. Instead set its permissions to 0777.
1705   ASSERT_TRUE(SetPosixFilePermissions(dst, 0777));
1706   ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
1707   EXPECT_EQ(0777, mode);
1708 
1709   // Overwrite it and check the permissions again.
1710   ASSERT_TRUE(CopyFile(src, dst));
1711   EXPECT_EQ(file_contents, ReadTextFile(dst));
1712   ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
1713   EXPECT_EQ(0777, mode);
1714 }
1715 
1716 #endif  // BUILDFLAG(IS_POSIX)
1717 
1718 #if !BUILDFLAG(IS_FUCHSIA)
1719 
TEST_F(FileUtilTest,CopyFileACL)1720 TEST_F(FileUtilTest, CopyFileACL) {
1721   // While FileUtilTest.CopyFile asserts the content is correctly copied over,
1722   // this test case asserts the access control bits are meeting expectations in
1723   // CopyFile().
1724   FilePath src = temp_dir_.GetPath().Append(FILE_PATH_LITERAL("src.txt"));
1725   const std::wstring file_contents(L"Gooooooooooooooooooooogle");
1726   CreateTextFile(src, file_contents);
1727 
1728   // Set the source file to read-only.
1729   ASSERT_FALSE(IsReadOnly(src));
1730   SetReadOnly(src, true);
1731   ASSERT_TRUE(IsReadOnly(src));
1732 
1733   // Copy the file.
1734   FilePath dst = temp_dir_.GetPath().Append(FILE_PATH_LITERAL("dst.txt"));
1735   ASSERT_TRUE(CopyFile(src, dst));
1736   EXPECT_EQ(file_contents, ReadTextFile(dst));
1737 
1738   ASSERT_FALSE(IsReadOnly(dst));
1739 }
1740 
TEST_F(FileUtilTest,CopyDirectoryACL)1741 TEST_F(FileUtilTest, CopyDirectoryACL) {
1742   // Create source directories.
1743   FilePath src = temp_dir_.GetPath().Append(FILE_PATH_LITERAL("src"));
1744   FilePath src_subdir = src.Append(FILE_PATH_LITERAL("subdir"));
1745   CreateDirectory(src_subdir);
1746   ASSERT_TRUE(PathExists(src_subdir));
1747 
1748   // Create a file under the directory.
1749   FilePath src_file = src.Append(FILE_PATH_LITERAL("src.txt"));
1750   CreateTextFile(src_file, L"Gooooooooooooooooooooogle");
1751   SetReadOnly(src_file, true);
1752   ASSERT_TRUE(IsReadOnly(src_file));
1753 
1754   // Make directory read-only.
1755   SetReadOnly(src_subdir, true);
1756   ASSERT_TRUE(IsReadOnly(src_subdir));
1757 
1758   // Copy the directory recursively.
1759   FilePath dst = temp_dir_.GetPath().Append(FILE_PATH_LITERAL("dst"));
1760   FilePath dst_file = dst.Append(FILE_PATH_LITERAL("src.txt"));
1761   EXPECT_TRUE(CopyDirectory(src, dst, true));
1762 
1763   FilePath dst_subdir = dst.Append(FILE_PATH_LITERAL("subdir"));
1764   ASSERT_FALSE(IsReadOnly(dst_subdir));
1765   ASSERT_FALSE(IsReadOnly(dst_file));
1766 
1767   // Give write permissions to allow deletion.
1768   SetReadOnly(src_subdir, false);
1769   ASSERT_FALSE(IsReadOnly(src_subdir));
1770 }
1771 
1772 #endif  // !BUILDFLAG(IS_FUCHSIA)
1773 
TEST_F(FileUtilTest,DeleteNonExistent)1774 TEST_F(FileUtilTest, DeleteNonExistent) {
1775   FilePath non_existent =
1776       temp_dir_.GetPath().AppendASCII("bogus_file_dne.foobar");
1777   ASSERT_FALSE(PathExists(non_existent));
1778 
1779   EXPECT_TRUE(DeleteFile(non_existent));
1780   ASSERT_FALSE(PathExists(non_existent));
1781   EXPECT_TRUE(DeletePathRecursively(non_existent));
1782   ASSERT_FALSE(PathExists(non_existent));
1783 }
1784 
TEST_F(FileUtilTest,DeleteNonExistentWithNonExistentParent)1785 TEST_F(FileUtilTest, DeleteNonExistentWithNonExistentParent) {
1786   FilePath non_existent = temp_dir_.GetPath().AppendASCII("bogus_topdir");
1787   non_existent = non_existent.AppendASCII("bogus_subdir");
1788   ASSERT_FALSE(PathExists(non_existent));
1789 
1790   EXPECT_TRUE(DeleteFile(non_existent));
1791   ASSERT_FALSE(PathExists(non_existent));
1792   EXPECT_TRUE(DeletePathRecursively(non_existent));
1793   ASSERT_FALSE(PathExists(non_existent));
1794 }
1795 
TEST_F(FileUtilTest,DeleteFile)1796 TEST_F(FileUtilTest, DeleteFile) {
1797   // Create a file
1798   FilePath file_name = temp_dir_.GetPath().Append(FPL("Test DeleteFile 1.txt"));
1799   CreateTextFile(file_name, bogus_content);
1800   ASSERT_TRUE(PathExists(file_name));
1801 
1802   // Make sure it's deleted
1803   EXPECT_TRUE(DeleteFile(file_name));
1804   EXPECT_FALSE(PathExists(file_name));
1805 
1806   // Test recursive case, create a new file
1807   file_name = temp_dir_.GetPath().Append(FPL("Test DeleteFile 2.txt"));
1808   CreateTextFile(file_name, bogus_content);
1809   ASSERT_TRUE(PathExists(file_name));
1810 
1811   // Make sure it's deleted
1812   EXPECT_TRUE(DeletePathRecursively(file_name));
1813   EXPECT_FALSE(PathExists(file_name));
1814 }
1815 
1816 #if BUILDFLAG(IS_ANDROID)
TEST_F(FileUtilTest,DeleteContentUri)1817 TEST_F(FileUtilTest, DeleteContentUri) {
1818   // Get the path to the test file.
1819   FilePath data_dir;
1820   ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
1821   data_dir = data_dir.Append(FPL("file_util"));
1822   ASSERT_TRUE(PathExists(data_dir));
1823   FilePath image_file = data_dir.Append(FPL("red.png"));
1824   ASSERT_TRUE(PathExists(image_file));
1825 
1826   // Make a copy (we don't want to delete the original red.png when deleting the
1827   // content URI).
1828   FilePath image_copy = data_dir.Append(FPL("redcopy.png"));
1829   ASSERT_TRUE(CopyFile(image_file, image_copy));
1830 
1831   // Insert the image into MediaStore and get a content URI.
1832   FilePath uri_path = InsertImageIntoMediaStore(image_copy);
1833   ASSERT_TRUE(uri_path.IsContentUri());
1834   ASSERT_TRUE(PathExists(uri_path));
1835 
1836   // Try deleting the content URI.
1837   EXPECT_TRUE(DeleteFile(uri_path));
1838   EXPECT_FALSE(PathExists(image_copy));
1839   EXPECT_FALSE(PathExists(uri_path));
1840 }
1841 #endif  // BUILDFLAG(IS_ANDROID)
1842 
1843 #if BUILDFLAG(IS_WIN)
1844 // Tests that the Delete function works for wild cards, especially
1845 // with the recursion flag.  Also coincidentally tests PathExists.
1846 // TODO(erikkay): see if anyone's actually using this feature of the API
TEST_F(FileUtilTest,DeleteWildCard)1847 TEST_F(FileUtilTest, DeleteWildCard) {
1848   // Create a file and a directory
1849   FilePath file_name =
1850       temp_dir_.GetPath().Append(FPL("Test DeleteWildCard.txt"));
1851   CreateTextFile(file_name, bogus_content);
1852   ASSERT_TRUE(PathExists(file_name));
1853 
1854   FilePath subdir_path = temp_dir_.GetPath().Append(FPL("DeleteWildCardDir"));
1855   CreateDirectory(subdir_path);
1856   ASSERT_TRUE(PathExists(subdir_path));
1857 
1858   // Create the wildcard path
1859   FilePath directory_contents = temp_dir_.GetPath();
1860   directory_contents = directory_contents.Append(FPL("*"));
1861 
1862   // Delete non-recursively and check that only the file is deleted
1863   EXPECT_TRUE(DeleteFile(directory_contents));
1864   EXPECT_FALSE(PathExists(file_name));
1865   EXPECT_TRUE(PathExists(subdir_path));
1866 
1867   // Delete recursively and make sure all contents are deleted
1868   EXPECT_TRUE(DeletePathRecursively(directory_contents));
1869   EXPECT_FALSE(PathExists(file_name));
1870   EXPECT_FALSE(PathExists(subdir_path));
1871 }
1872 
1873 // TODO(erikkay): see if anyone's actually using this feature of the API
TEST_F(FileUtilTest,DeleteNonExistantWildCard)1874 TEST_F(FileUtilTest, DeleteNonExistantWildCard) {
1875   // Create a file and a directory
1876   FilePath subdir_path =
1877       temp_dir_.GetPath().Append(FPL("DeleteNonExistantWildCard"));
1878   CreateDirectory(subdir_path);
1879   ASSERT_TRUE(PathExists(subdir_path));
1880 
1881   // Create the wildcard path
1882   FilePath directory_contents = subdir_path;
1883   directory_contents = directory_contents.Append(FPL("*"));
1884 
1885   // Delete non-recursively and check nothing got deleted
1886   EXPECT_TRUE(DeleteFile(directory_contents));
1887   EXPECT_TRUE(PathExists(subdir_path));
1888 
1889   // Delete recursively and check nothing got deleted
1890   EXPECT_TRUE(DeletePathRecursively(directory_contents));
1891   EXPECT_TRUE(PathExists(subdir_path));
1892 }
1893 #endif
1894 
1895 // Tests non-recursive Delete() for a directory.
TEST_F(FileUtilTest,DeleteDirNonRecursive)1896 TEST_F(FileUtilTest, DeleteDirNonRecursive) {
1897   // Create a subdirectory and put a file and two directories inside.
1898   FilePath test_subdir =
1899       temp_dir_.GetPath().Append(FPL("DeleteDirNonRecursive"));
1900   CreateDirectory(test_subdir);
1901   ASSERT_TRUE(PathExists(test_subdir));
1902 
1903   FilePath file_name = test_subdir.Append(FPL("Test DeleteDir.txt"));
1904   CreateTextFile(file_name, bogus_content);
1905   ASSERT_TRUE(PathExists(file_name));
1906 
1907   FilePath subdir_path1 = test_subdir.Append(FPL("TestSubDir1"));
1908   CreateDirectory(subdir_path1);
1909   ASSERT_TRUE(PathExists(subdir_path1));
1910 
1911   FilePath subdir_path2 = test_subdir.Append(FPL("TestSubDir2"));
1912   CreateDirectory(subdir_path2);
1913   ASSERT_TRUE(PathExists(subdir_path2));
1914 
1915   // Delete non-recursively and check that the empty dir got deleted
1916   EXPECT_TRUE(DeleteFile(subdir_path2));
1917   EXPECT_FALSE(PathExists(subdir_path2));
1918 
1919   // Delete non-recursively and check that nothing got deleted
1920   EXPECT_FALSE(DeleteFile(test_subdir));
1921   EXPECT_TRUE(PathExists(test_subdir));
1922   EXPECT_TRUE(PathExists(file_name));
1923   EXPECT_TRUE(PathExists(subdir_path1));
1924 }
1925 
1926 // Tests recursive Delete() for a directory.
TEST_F(FileUtilTest,DeleteDirRecursive)1927 TEST_F(FileUtilTest, DeleteDirRecursive) {
1928   // Create a subdirectory and put a file and two directories inside.
1929   FilePath test_subdir = temp_dir_.GetPath().Append(FPL("DeleteDirRecursive"));
1930   CreateDirectory(test_subdir);
1931   ASSERT_TRUE(PathExists(test_subdir));
1932 
1933   FilePath file_name = test_subdir.Append(FPL("Test DeleteDirRecursive.txt"));
1934   CreateTextFile(file_name, bogus_content);
1935   ASSERT_TRUE(PathExists(file_name));
1936 
1937   FilePath subdir_path1 = test_subdir.Append(FPL("TestSubDir1"));
1938   CreateDirectory(subdir_path1);
1939   ASSERT_TRUE(PathExists(subdir_path1));
1940 
1941   FilePath subdir_path2 = test_subdir.Append(FPL("TestSubDir2"));
1942   CreateDirectory(subdir_path2);
1943   ASSERT_TRUE(PathExists(subdir_path2));
1944 
1945   // Delete recursively and check that the empty dir got deleted
1946   EXPECT_TRUE(DeletePathRecursively(subdir_path2));
1947   EXPECT_FALSE(PathExists(subdir_path2));
1948 
1949   // Delete recursively and check that everything got deleted
1950   EXPECT_TRUE(DeletePathRecursively(test_subdir));
1951   EXPECT_FALSE(PathExists(file_name));
1952   EXPECT_FALSE(PathExists(subdir_path1));
1953   EXPECT_FALSE(PathExists(test_subdir));
1954 }
1955 
1956 // Tests recursive Delete() for a directory.
TEST_F(FileUtilTest,DeleteDirRecursiveWithOpenFile)1957 TEST_F(FileUtilTest, DeleteDirRecursiveWithOpenFile) {
1958   // Create a subdirectory and put a file and two directories inside.
1959   FilePath test_subdir = temp_dir_.GetPath().Append(FPL("DeleteWithOpenFile"));
1960   CreateDirectory(test_subdir);
1961   ASSERT_TRUE(PathExists(test_subdir));
1962 
1963   FilePath file_name1 = test_subdir.Append(FPL("Undeletebable File1.txt"));
1964   File file1(file_name1,
1965              File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE);
1966   ASSERT_TRUE(PathExists(file_name1));
1967 
1968   FilePath file_name2 = test_subdir.Append(FPL("Deleteable File2.txt"));
1969   CreateTextFile(file_name2, bogus_content);
1970   ASSERT_TRUE(PathExists(file_name2));
1971 
1972   FilePath file_name3 = test_subdir.Append(FPL("Undeletebable File3.txt"));
1973   File file3(file_name3,
1974              File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE);
1975   ASSERT_TRUE(PathExists(file_name3));
1976 
1977 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
1978   // On Windows, holding the file open in sufficient to make it un-deletable.
1979   // The POSIX code is verifiable on Linux by creating an "immutable" file but
1980   // this is best-effort because it's not supported by all file systems. Both
1981   // files will have the same flags so no need to get them individually.
1982   int flags;
1983   bool file_attrs_supported =
1984       ioctl(file1.GetPlatformFile(), FS_IOC_GETFLAGS, &flags) == 0;
1985   // Some filesystems (e.g. tmpfs) don't support file attributes.
1986   if (file_attrs_supported) {
1987     flags |= FS_IMMUTABLE_FL;
1988     ioctl(file1.GetPlatformFile(), FS_IOC_SETFLAGS, &flags);
1989     ioctl(file3.GetPlatformFile(), FS_IOC_SETFLAGS, &flags);
1990   }
1991 #endif
1992 
1993   // Delete recursively and check that at least the second file got deleted.
1994   // This ensures that un-deletable files don't impact those that can be.
1995   DeletePathRecursively(test_subdir);
1996   EXPECT_FALSE(PathExists(file_name2));
1997 
1998 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
1999   // Make sure that the test can clean up after itself.
2000   if (file_attrs_supported) {
2001     flags &= ~FS_IMMUTABLE_FL;
2002     ioctl(file1.GetPlatformFile(), FS_IOC_SETFLAGS, &flags);
2003     ioctl(file3.GetPlatformFile(), FS_IOC_SETFLAGS, &flags);
2004   }
2005 #endif
2006 }
2007 
2008 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
2009 // This test will validate that files which would block when read result in a
2010 // failure on a call to ReadFileToStringNonBlocking. To accomplish this we will
2011 // use a named pipe because it appears as a file on disk and we can control how
2012 // much data is available to read. This allows us to simulate a file which would
2013 // block.
TEST_F(FileUtilTest,TestNonBlockingFileReadLinux)2014 TEST_F(FileUtilTest, TestNonBlockingFileReadLinux) {
2015   FilePath fifo_path = temp_dir_.GetPath().Append(FPL("fifo"));
2016   int res = mkfifo(fifo_path.MaybeAsASCII().c_str(),
2017                    S_IWUSR | S_IRUSR | S_IWGRP | S_IWGRP);
2018   ASSERT_NE(res, -1);
2019 
2020   base::ScopedFD fd(open(fifo_path.MaybeAsASCII().c_str(), O_RDWR));
2021   ASSERT_TRUE(fd.is_valid());
2022 
2023   std::string result;
2024   // We will try to read when nothing is available on the fifo, the output
2025   // string will be unmodified and it will fail with EWOULDBLOCK.
2026   ASSERT_FALSE(ReadFileToStringNonBlocking(fifo_path, &result));
2027   EXPECT_EQ(errno, EWOULDBLOCK);
2028   EXPECT_TRUE(result.empty());
2029 
2030   // Make a single byte available to read on the FIFO.
2031   ASSERT_EQ(write(fd.get(), "a", 1), 1);
2032 
2033   // Now the key part of the test we will call ReadFromFileNonBlocking which
2034   // should fail, errno will be EWOULDBLOCK and the output string will contain
2035   // the single 'a' byte.
2036   ASSERT_FALSE(ReadFileToStringNonBlocking(fifo_path, &result));
2037   EXPECT_EQ(errno, EWOULDBLOCK);
2038   ASSERT_EQ(result.size(), 1u);
2039   EXPECT_EQ(result[0], 'a');
2040 }
2041 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
2042 
TEST_F(FileUtilTest,MoveFileNew)2043 TEST_F(FileUtilTest, MoveFileNew) {
2044   // Create a file
2045   FilePath file_name_from =
2046       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
2047   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2048   ASSERT_TRUE(PathExists(file_name_from));
2049 
2050   // The destination.
2051   FilePath file_name_to = temp_dir_.GetPath().Append(
2052       FILE_PATH_LITERAL("Move_Test_File_Destination.txt"));
2053   ASSERT_FALSE(PathExists(file_name_to));
2054 
2055   EXPECT_TRUE(Move(file_name_from, file_name_to));
2056 
2057   // Check everything has been moved.
2058   EXPECT_FALSE(PathExists(file_name_from));
2059   EXPECT_TRUE(PathExists(file_name_to));
2060 }
2061 
TEST_F(FileUtilTest,MoveFileExists)2062 TEST_F(FileUtilTest, MoveFileExists) {
2063   // Create a file
2064   FilePath file_name_from =
2065       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
2066   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2067   ASSERT_TRUE(PathExists(file_name_from));
2068 
2069   // The destination name.
2070   FilePath file_name_to = temp_dir_.GetPath().Append(
2071       FILE_PATH_LITERAL("Move_Test_File_Destination.txt"));
2072   CreateTextFile(file_name_to, L"Old file content");
2073   ASSERT_TRUE(PathExists(file_name_to));
2074 
2075   EXPECT_TRUE(Move(file_name_from, file_name_to));
2076 
2077   // Check everything has been moved.
2078   EXPECT_FALSE(PathExists(file_name_from));
2079   EXPECT_TRUE(PathExists(file_name_to));
2080   EXPECT_TRUE(L"Gooooooooooooooooooooogle" == ReadTextFile(file_name_to));
2081 }
2082 
TEST_F(FileUtilTest,MoveFileDirExists)2083 TEST_F(FileUtilTest, MoveFileDirExists) {
2084   // Create a file
2085   FilePath file_name_from =
2086       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
2087   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2088   ASSERT_TRUE(PathExists(file_name_from));
2089 
2090   // The destination directory
2091   FilePath dir_name_to =
2092       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Destination"));
2093   CreateDirectory(dir_name_to);
2094   ASSERT_TRUE(PathExists(dir_name_to));
2095 
2096   EXPECT_FALSE(Move(file_name_from, dir_name_to));
2097 }
2098 
2099 
TEST_F(FileUtilTest,MoveNew)2100 TEST_F(FileUtilTest, MoveNew) {
2101   // Create a directory
2102   FilePath dir_name_from =
2103       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_From_Subdir"));
2104   CreateDirectory(dir_name_from);
2105   ASSERT_TRUE(PathExists(dir_name_from));
2106 
2107   // Create a file under the directory
2108   FilePath txt_file_name(FILE_PATH_LITERAL("Move_Test_File.txt"));
2109   FilePath file_name_from = dir_name_from.Append(txt_file_name);
2110   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2111   ASSERT_TRUE(PathExists(file_name_from));
2112 
2113   // Move the directory.
2114   FilePath dir_name_to =
2115       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_To_Subdir"));
2116   FilePath file_name_to =
2117       dir_name_to.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
2118 
2119   ASSERT_FALSE(PathExists(dir_name_to));
2120 
2121   EXPECT_TRUE(Move(dir_name_from, dir_name_to));
2122 
2123   // Check everything has been moved.
2124   EXPECT_FALSE(PathExists(dir_name_from));
2125   EXPECT_FALSE(PathExists(file_name_from));
2126   EXPECT_TRUE(PathExists(dir_name_to));
2127   EXPECT_TRUE(PathExists(file_name_to));
2128 
2129   // Test path traversal.
2130   file_name_from = dir_name_to.Append(txt_file_name);
2131   file_name_to = dir_name_to.Append(FILE_PATH_LITERAL(".."));
2132   file_name_to = file_name_to.Append(txt_file_name);
2133   EXPECT_FALSE(Move(file_name_from, file_name_to));
2134   EXPECT_TRUE(PathExists(file_name_from));
2135   EXPECT_FALSE(PathExists(file_name_to));
2136   EXPECT_TRUE(internal::MoveUnsafe(file_name_from, file_name_to));
2137   EXPECT_FALSE(PathExists(file_name_from));
2138   EXPECT_TRUE(PathExists(file_name_to));
2139 }
2140 
TEST_F(FileUtilTest,MoveExist)2141 TEST_F(FileUtilTest, MoveExist) {
2142   // Create a directory
2143   FilePath dir_name_from =
2144       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_From_Subdir"));
2145   CreateDirectory(dir_name_from);
2146   ASSERT_TRUE(PathExists(dir_name_from));
2147 
2148   // Create a file under the directory
2149   FilePath file_name_from =
2150       dir_name_from.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
2151   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2152   ASSERT_TRUE(PathExists(file_name_from));
2153 
2154   // Move the directory
2155   FilePath dir_name_exists =
2156       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Destination"));
2157 
2158   FilePath dir_name_to =
2159       dir_name_exists.Append(FILE_PATH_LITERAL("Move_To_Subdir"));
2160   FilePath file_name_to =
2161       dir_name_to.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
2162 
2163   // Create the destination directory.
2164   CreateDirectory(dir_name_exists);
2165   ASSERT_TRUE(PathExists(dir_name_exists));
2166 
2167   EXPECT_TRUE(Move(dir_name_from, dir_name_to));
2168 
2169   // Check everything has been moved.
2170   EXPECT_FALSE(PathExists(dir_name_from));
2171   EXPECT_FALSE(PathExists(file_name_from));
2172   EXPECT_TRUE(PathExists(dir_name_to));
2173   EXPECT_TRUE(PathExists(file_name_to));
2174 }
2175 
TEST_F(FileUtilTest,CopyDirectoryRecursivelyNew)2176 TEST_F(FileUtilTest, CopyDirectoryRecursivelyNew) {
2177   // Create a directory.
2178   FilePath dir_name_from =
2179       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2180   CreateDirectory(dir_name_from);
2181   ASSERT_TRUE(PathExists(dir_name_from));
2182 
2183   // Create a file under the directory.
2184   FilePath file_name_from =
2185       dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2186   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2187   ASSERT_TRUE(PathExists(file_name_from));
2188 
2189   // Create a subdirectory.
2190   FilePath subdir_name_from =
2191       dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
2192   CreateDirectory(subdir_name_from);
2193   ASSERT_TRUE(PathExists(subdir_name_from));
2194 
2195   // Create a file under the subdirectory.
2196   FilePath file_name2_from =
2197       subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2198   CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
2199   ASSERT_TRUE(PathExists(file_name2_from));
2200 
2201   // Copy the directory recursively.
2202   FilePath dir_name_to =
2203       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2204   FilePath file_name_to =
2205       dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2206   FilePath subdir_name_to =
2207       dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
2208   FilePath file_name2_to =
2209       subdir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2210 
2211   ASSERT_FALSE(PathExists(dir_name_to));
2212 
2213   EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, true));
2214 
2215   // Check everything has been copied.
2216   EXPECT_TRUE(PathExists(dir_name_from));
2217   EXPECT_TRUE(PathExists(file_name_from));
2218   EXPECT_TRUE(PathExists(subdir_name_from));
2219   EXPECT_TRUE(PathExists(file_name2_from));
2220   EXPECT_TRUE(PathExists(dir_name_to));
2221   EXPECT_TRUE(PathExists(file_name_to));
2222   EXPECT_TRUE(PathExists(subdir_name_to));
2223   EXPECT_TRUE(PathExists(file_name2_to));
2224 }
2225 
TEST_F(FileUtilTest,CopyDirectoryRecursivelyExists)2226 TEST_F(FileUtilTest, CopyDirectoryRecursivelyExists) {
2227   // Create a directory.
2228   FilePath dir_name_from =
2229       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2230   CreateDirectory(dir_name_from);
2231   ASSERT_TRUE(PathExists(dir_name_from));
2232 
2233   // Create a file under the directory.
2234   FilePath file_name_from =
2235       dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2236   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2237   ASSERT_TRUE(PathExists(file_name_from));
2238 
2239   // Create a subdirectory.
2240   FilePath subdir_name_from =
2241       dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
2242   CreateDirectory(subdir_name_from);
2243   ASSERT_TRUE(PathExists(subdir_name_from));
2244 
2245   // Create a file under the subdirectory.
2246   FilePath file_name2_from =
2247       subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2248   CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
2249   ASSERT_TRUE(PathExists(file_name2_from));
2250 
2251   // Copy the directory recursively.
2252   FilePath dir_name_exists =
2253       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Destination"));
2254 
2255   FilePath dir_name_to =
2256       dir_name_exists.Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2257   FilePath file_name_to =
2258       dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2259   FilePath subdir_name_to =
2260       dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
2261   FilePath file_name2_to =
2262       subdir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2263 
2264   // Create the destination directory.
2265   CreateDirectory(dir_name_exists);
2266   ASSERT_TRUE(PathExists(dir_name_exists));
2267 
2268   EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_exists, true));
2269 
2270   // Check everything has been copied.
2271   EXPECT_TRUE(PathExists(dir_name_from));
2272   EXPECT_TRUE(PathExists(file_name_from));
2273   EXPECT_TRUE(PathExists(subdir_name_from));
2274   EXPECT_TRUE(PathExists(file_name2_from));
2275   EXPECT_TRUE(PathExists(dir_name_to));
2276   EXPECT_TRUE(PathExists(file_name_to));
2277   EXPECT_TRUE(PathExists(subdir_name_to));
2278   EXPECT_TRUE(PathExists(file_name2_to));
2279 }
2280 
TEST_F(FileUtilTest,CopyDirectoryNew)2281 TEST_F(FileUtilTest, CopyDirectoryNew) {
2282   // Create a directory.
2283   FilePath dir_name_from =
2284       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2285   CreateDirectory(dir_name_from);
2286   ASSERT_TRUE(PathExists(dir_name_from));
2287 
2288   // Create a file under the directory.
2289   FilePath file_name_from =
2290       dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2291   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2292   ASSERT_TRUE(PathExists(file_name_from));
2293 
2294   // Create a subdirectory.
2295   FilePath subdir_name_from =
2296       dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
2297   CreateDirectory(subdir_name_from);
2298   ASSERT_TRUE(PathExists(subdir_name_from));
2299 
2300   // Create a file under the subdirectory.
2301   FilePath file_name2_from =
2302       subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2303   CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
2304   ASSERT_TRUE(PathExists(file_name2_from));
2305 
2306   // Copy the directory not recursively.
2307   FilePath dir_name_to =
2308       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2309   FilePath file_name_to =
2310       dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2311   FilePath subdir_name_to =
2312       dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
2313 
2314   ASSERT_FALSE(PathExists(dir_name_to));
2315 
2316   EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
2317 
2318   // Check everything has been copied.
2319   EXPECT_TRUE(PathExists(dir_name_from));
2320   EXPECT_TRUE(PathExists(file_name_from));
2321   EXPECT_TRUE(PathExists(subdir_name_from));
2322   EXPECT_TRUE(PathExists(file_name2_from));
2323   EXPECT_TRUE(PathExists(dir_name_to));
2324   EXPECT_TRUE(PathExists(file_name_to));
2325   EXPECT_FALSE(PathExists(subdir_name_to));
2326 }
2327 
TEST_F(FileUtilTest,CopyDirectoryExists)2328 TEST_F(FileUtilTest, CopyDirectoryExists) {
2329   // Create a directory.
2330   FilePath dir_name_from =
2331       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2332   CreateDirectory(dir_name_from);
2333   ASSERT_TRUE(PathExists(dir_name_from));
2334 
2335   // Create a file under the directory.
2336   FilePath file_name_from =
2337       dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2338   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2339   ASSERT_TRUE(PathExists(file_name_from));
2340 
2341   // Create a subdirectory.
2342   FilePath subdir_name_from =
2343       dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
2344   CreateDirectory(subdir_name_from);
2345   ASSERT_TRUE(PathExists(subdir_name_from));
2346 
2347   // Create a file under the subdirectory.
2348   FilePath file_name2_from =
2349       subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2350   CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
2351   ASSERT_TRUE(PathExists(file_name2_from));
2352 
2353   // Copy the directory not recursively.
2354   FilePath dir_name_to =
2355       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2356   FilePath file_name_to =
2357       dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2358   FilePath subdir_name_to =
2359       dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
2360 
2361   // Create the destination directory.
2362   CreateDirectory(dir_name_to);
2363   ASSERT_TRUE(PathExists(dir_name_to));
2364 
2365   EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
2366 
2367   // Check everything has been copied.
2368   EXPECT_TRUE(PathExists(dir_name_from));
2369   EXPECT_TRUE(PathExists(file_name_from));
2370   EXPECT_TRUE(PathExists(subdir_name_from));
2371   EXPECT_TRUE(PathExists(file_name2_from));
2372   EXPECT_TRUE(PathExists(dir_name_to));
2373   EXPECT_TRUE(PathExists(file_name_to));
2374   EXPECT_FALSE(PathExists(subdir_name_to));
2375 }
2376 
TEST_F(FileUtilTest,CopyFileWithCopyDirectoryRecursiveToNew)2377 TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToNew) {
2378   // Create a file
2379   FilePath file_name_from =
2380       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2381   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2382   ASSERT_TRUE(PathExists(file_name_from));
2383 
2384   // The destination name
2385   FilePath file_name_to = temp_dir_.GetPath().Append(
2386       FILE_PATH_LITERAL("Copy_Test_File_Destination.txt"));
2387   ASSERT_FALSE(PathExists(file_name_to));
2388 
2389   EXPECT_TRUE(CopyDirectory(file_name_from, file_name_to, true));
2390 
2391   // Check the has been copied
2392   EXPECT_TRUE(PathExists(file_name_to));
2393 }
2394 
TEST_F(FileUtilTest,CopyFileWithCopyDirectoryRecursiveToExisting)2395 TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToExisting) {
2396   // Create a file
2397   FilePath file_name_from =
2398       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2399   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2400   ASSERT_TRUE(PathExists(file_name_from));
2401 
2402   // The destination name
2403   FilePath file_name_to = temp_dir_.GetPath().Append(
2404       FILE_PATH_LITERAL("Copy_Test_File_Destination.txt"));
2405   CreateTextFile(file_name_to, L"Old file content");
2406   ASSERT_TRUE(PathExists(file_name_to));
2407 
2408   EXPECT_TRUE(CopyDirectory(file_name_from, file_name_to, true));
2409 
2410   // Check the has been copied
2411   EXPECT_TRUE(PathExists(file_name_to));
2412   EXPECT_TRUE(L"Gooooooooooooooooooooogle" == ReadTextFile(file_name_to));
2413 }
2414 
TEST_F(FileUtilTest,CopyFileWithCopyDirectoryRecursiveToExistingDirectory)2415 TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToExistingDirectory) {
2416   // Create a file
2417   FilePath file_name_from =
2418       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2419   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2420   ASSERT_TRUE(PathExists(file_name_from));
2421 
2422   // The destination
2423   FilePath dir_name_to =
2424       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Destination"));
2425   CreateDirectory(dir_name_to);
2426   ASSERT_TRUE(PathExists(dir_name_to));
2427   FilePath file_name_to =
2428       dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2429 
2430   EXPECT_TRUE(CopyDirectory(file_name_from, dir_name_to, true));
2431 
2432   // Check the has been copied
2433   EXPECT_TRUE(PathExists(file_name_to));
2434 }
2435 
TEST_F(FileUtilTest,CopyFileFailureWithCopyDirectoryExcl)2436 TEST_F(FileUtilTest, CopyFileFailureWithCopyDirectoryExcl) {
2437   // Create a file
2438   FilePath file_name_from =
2439       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2440   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2441   ASSERT_TRUE(PathExists(file_name_from));
2442 
2443   // Make a destination file.
2444   FilePath file_name_to = temp_dir_.GetPath().Append(
2445       FILE_PATH_LITERAL("Copy_Test_File_Destination.txt"));
2446   CreateTextFile(file_name_to, L"Old file content");
2447   ASSERT_TRUE(PathExists(file_name_to));
2448 
2449   // Overwriting the destination should fail.
2450   EXPECT_FALSE(CopyDirectoryExcl(file_name_from, file_name_to, true));
2451   EXPECT_EQ(L"Old file content", ReadTextFile(file_name_to));
2452 }
2453 
TEST_F(FileUtilTest,CopyDirectoryWithTrailingSeparators)2454 TEST_F(FileUtilTest, CopyDirectoryWithTrailingSeparators) {
2455   // Create a directory.
2456   FilePath dir_name_from =
2457       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2458   CreateDirectory(dir_name_from);
2459   ASSERT_TRUE(PathExists(dir_name_from));
2460 
2461   // Create a file under the directory.
2462   FilePath file_name_from =
2463       dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2464   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2465   ASSERT_TRUE(PathExists(file_name_from));
2466 
2467   // Copy the directory recursively.
2468   FilePath dir_name_to =
2469       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2470   FilePath file_name_to =
2471       dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2472 
2473   // Create from path with trailing separators.
2474 #if BUILDFLAG(IS_WIN)
2475   FilePath from_path =
2476       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir\\\\\\"));
2477 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
2478   FilePath from_path =
2479       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir///"));
2480 #endif
2481 
2482   EXPECT_TRUE(CopyDirectory(from_path, dir_name_to, true));
2483 
2484   // Check everything has been copied.
2485   EXPECT_TRUE(PathExists(dir_name_from));
2486   EXPECT_TRUE(PathExists(file_name_from));
2487   EXPECT_TRUE(PathExists(dir_name_to));
2488   EXPECT_TRUE(PathExists(file_name_to));
2489 }
2490 
2491 #if BUILDFLAG(IS_POSIX)
TEST_F(FileUtilTest,CopyDirectoryWithNonRegularFiles)2492 TEST_F(FileUtilTest, CopyDirectoryWithNonRegularFiles) {
2493   // Create a directory.
2494   FilePath dir_name_from =
2495       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2496   ASSERT_TRUE(CreateDirectory(dir_name_from));
2497   ASSERT_TRUE(PathExists(dir_name_from));
2498 
2499   // Create a file under the directory.
2500   FilePath file_name_from =
2501       dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2502   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2503   ASSERT_TRUE(PathExists(file_name_from));
2504 
2505   // Create a symbolic link under the directory pointing to that file.
2506   FilePath symlink_name_from =
2507       dir_name_from.Append(FILE_PATH_LITERAL("Symlink"));
2508   ASSERT_TRUE(CreateSymbolicLink(file_name_from, symlink_name_from));
2509   ASSERT_TRUE(PathExists(symlink_name_from));
2510 
2511   // Create a fifo under the directory.
2512   FilePath fifo_name_from =
2513       dir_name_from.Append(FILE_PATH_LITERAL("Fifo"));
2514   ASSERT_EQ(0, mkfifo(fifo_name_from.value().c_str(), 0644));
2515   ASSERT_TRUE(PathExists(fifo_name_from));
2516 
2517   // Copy the directory.
2518   FilePath dir_name_to =
2519       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2520   FilePath file_name_to =
2521       dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2522   FilePath symlink_name_to =
2523       dir_name_to.Append(FILE_PATH_LITERAL("Symlink"));
2524   FilePath fifo_name_to =
2525       dir_name_to.Append(FILE_PATH_LITERAL("Fifo"));
2526 
2527   ASSERT_FALSE(PathExists(dir_name_to));
2528 
2529   EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
2530 
2531   // Check that only directories and regular files are copied.
2532   EXPECT_TRUE(PathExists(dir_name_from));
2533   EXPECT_TRUE(PathExists(file_name_from));
2534   EXPECT_TRUE(PathExists(symlink_name_from));
2535   EXPECT_TRUE(PathExists(fifo_name_from));
2536   EXPECT_TRUE(PathExists(dir_name_to));
2537   EXPECT_TRUE(PathExists(file_name_to));
2538   EXPECT_FALSE(PathExists(symlink_name_to));
2539   EXPECT_FALSE(PathExists(fifo_name_to));
2540 }
2541 
TEST_F(FileUtilTest,CopyDirectoryExclFileOverSymlink)2542 TEST_F(FileUtilTest, CopyDirectoryExclFileOverSymlink) {
2543   // Create a directory.
2544   FilePath dir_name_from =
2545       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2546   ASSERT_TRUE(CreateDirectory(dir_name_from));
2547   ASSERT_TRUE(PathExists(dir_name_from));
2548 
2549   // Create a file under the directory.
2550   FilePath file_name_from =
2551       dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2552   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2553   ASSERT_TRUE(PathExists(file_name_from));
2554 
2555   // Create a destination directory with a symlink of the same name.
2556   FilePath dir_name_to =
2557       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2558   ASSERT_TRUE(CreateDirectory(dir_name_to));
2559   ASSERT_TRUE(PathExists(dir_name_to));
2560 
2561   FilePath symlink_target =
2562       dir_name_to.Append(FILE_PATH_LITERAL("Symlink_Target.txt"));
2563   CreateTextFile(symlink_target, L"asdf");
2564   ASSERT_TRUE(PathExists(symlink_target));
2565 
2566   FilePath symlink_name_to =
2567       dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2568   ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to));
2569   ASSERT_TRUE(PathExists(symlink_name_to));
2570 
2571   // Check that copying fails.
2572   EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
2573 }
2574 
TEST_F(FileUtilTest,CopyDirectoryExclDirectoryOverSymlink)2575 TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverSymlink) {
2576   // Create a directory.
2577   FilePath dir_name_from =
2578       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2579   ASSERT_TRUE(CreateDirectory(dir_name_from));
2580   ASSERT_TRUE(PathExists(dir_name_from));
2581 
2582   // Create a subdirectory.
2583   FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub"));
2584   CreateDirectory(subdir_name_from);
2585   ASSERT_TRUE(PathExists(subdir_name_from));
2586 
2587   // Create a destination directory with a symlink of the same name.
2588   FilePath dir_name_to =
2589       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2590   ASSERT_TRUE(CreateDirectory(dir_name_to));
2591   ASSERT_TRUE(PathExists(dir_name_to));
2592 
2593   FilePath symlink_target = dir_name_to.Append(FILE_PATH_LITERAL("Subsub"));
2594   CreateTextFile(symlink_target, L"asdf");
2595   ASSERT_TRUE(PathExists(symlink_target));
2596 
2597   FilePath symlink_name_to =
2598       dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2599   ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to));
2600   ASSERT_TRUE(PathExists(symlink_name_to));
2601 
2602   // Check that copying fails.
2603   EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
2604 }
2605 
TEST_F(FileUtilTest,CopyDirectoryExclFileOverDanglingSymlink)2606 TEST_F(FileUtilTest, CopyDirectoryExclFileOverDanglingSymlink) {
2607   // Create a directory.
2608   FilePath dir_name_from =
2609       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2610   ASSERT_TRUE(CreateDirectory(dir_name_from));
2611   ASSERT_TRUE(PathExists(dir_name_from));
2612 
2613   // Create a file under the directory.
2614   FilePath file_name_from =
2615       dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2616   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2617   ASSERT_TRUE(PathExists(file_name_from));
2618 
2619   // Create a destination directory with a dangling symlink of the same name.
2620   FilePath dir_name_to =
2621       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2622   ASSERT_TRUE(CreateDirectory(dir_name_to));
2623   ASSERT_TRUE(PathExists(dir_name_to));
2624 
2625   FilePath symlink_target =
2626       dir_name_to.Append(FILE_PATH_LITERAL("Symlink_Target.txt"));
2627   CreateTextFile(symlink_target, L"asdf");
2628   ASSERT_TRUE(PathExists(symlink_target));
2629 
2630   FilePath symlink_name_to =
2631       dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2632   ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to));
2633   ASSERT_TRUE(PathExists(symlink_name_to));
2634   ASSERT_TRUE(DeleteFile(symlink_target));
2635 
2636   // Check that copying fails and that no file was created for the symlink's
2637   // referent.
2638   EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
2639   EXPECT_FALSE(PathExists(symlink_target));
2640 }
2641 
TEST_F(FileUtilTest,CopyDirectoryExclDirectoryOverDanglingSymlink)2642 TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverDanglingSymlink) {
2643   // Create a directory.
2644   FilePath dir_name_from =
2645       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2646   ASSERT_TRUE(CreateDirectory(dir_name_from));
2647   ASSERT_TRUE(PathExists(dir_name_from));
2648 
2649   // Create a subdirectory.
2650   FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub"));
2651   CreateDirectory(subdir_name_from);
2652   ASSERT_TRUE(PathExists(subdir_name_from));
2653 
2654   // Create a destination directory with a dangling symlink of the same name.
2655   FilePath dir_name_to =
2656       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2657   ASSERT_TRUE(CreateDirectory(dir_name_to));
2658   ASSERT_TRUE(PathExists(dir_name_to));
2659 
2660   FilePath symlink_target =
2661       dir_name_to.Append(FILE_PATH_LITERAL("Symlink_Target.txt"));
2662   CreateTextFile(symlink_target, L"asdf");
2663   ASSERT_TRUE(PathExists(symlink_target));
2664 
2665   FilePath symlink_name_to =
2666       dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2667   ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to));
2668   ASSERT_TRUE(PathExists(symlink_name_to));
2669   ASSERT_TRUE(DeleteFile(symlink_target));
2670 
2671   // Check that copying fails and that no directory was created for the
2672   // symlink's referent.
2673   EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
2674   EXPECT_FALSE(PathExists(symlink_target));
2675 }
2676 
TEST_F(FileUtilTest,CopyDirectoryExclFileOverFifo)2677 TEST_F(FileUtilTest, CopyDirectoryExclFileOverFifo) {
2678   // Create a directory.
2679   FilePath dir_name_from =
2680       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2681   ASSERT_TRUE(CreateDirectory(dir_name_from));
2682   ASSERT_TRUE(PathExists(dir_name_from));
2683 
2684   // Create a file under the directory.
2685   FilePath file_name_from =
2686       dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2687   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2688   ASSERT_TRUE(PathExists(file_name_from));
2689 
2690   // Create a destination directory with a fifo of the same name.
2691   FilePath dir_name_to =
2692       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2693   ASSERT_TRUE(CreateDirectory(dir_name_to));
2694   ASSERT_TRUE(PathExists(dir_name_to));
2695 
2696   FilePath fifo_name_to =
2697       dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2698   ASSERT_EQ(0, mkfifo(fifo_name_to.value().c_str(), 0644));
2699   ASSERT_TRUE(PathExists(fifo_name_to));
2700 
2701   // Check that copying fails.
2702   EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
2703 }
2704 #endif  // BUILDFLAG(IS_POSIX)
2705 
TEST_F(FileUtilTest,CopyFile)2706 TEST_F(FileUtilTest, CopyFile) {
2707   // Create a directory
2708   FilePath dir_name_from =
2709       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2710   ASSERT_TRUE(CreateDirectory(dir_name_from));
2711   ASSERT_TRUE(DirectoryExists(dir_name_from));
2712 
2713   // Create a file under the directory
2714   FilePath file_name_from =
2715       dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2716   const std::wstring file_contents(L"Gooooooooooooooooooooogle");
2717   CreateTextFile(file_name_from, file_contents);
2718   ASSERT_TRUE(PathExists(file_name_from));
2719 
2720   // Copy the file.
2721   FilePath dest_file = dir_name_from.Append(FILE_PATH_LITERAL("DestFile.txt"));
2722   ASSERT_TRUE(CopyFile(file_name_from, dest_file));
2723 
2724   // Try to copy the file to another location using '..' in the path.
2725   FilePath dest_file2(dir_name_from);
2726   dest_file2 = dest_file2.AppendASCII("..");
2727   dest_file2 = dest_file2.AppendASCII("DestFile.txt");
2728   ASSERT_FALSE(CopyFile(file_name_from, dest_file2));
2729 
2730   FilePath dest_file2_test(dir_name_from);
2731   dest_file2_test = dest_file2_test.DirName();
2732   dest_file2_test = dest_file2_test.AppendASCII("DestFile.txt");
2733 
2734   // Check expected copy results.
2735   EXPECT_TRUE(PathExists(file_name_from));
2736   EXPECT_TRUE(PathExists(dest_file));
2737   EXPECT_EQ(file_contents, ReadTextFile(dest_file));
2738   EXPECT_FALSE(PathExists(dest_file2_test));
2739   EXPECT_FALSE(PathExists(dest_file2));
2740 
2741   // Change |file_name_from| contents.
2742   const std::wstring new_file_contents(L"Moogle");
2743   CreateTextFile(file_name_from, new_file_contents);
2744   ASSERT_TRUE(PathExists(file_name_from));
2745   EXPECT_EQ(new_file_contents, ReadTextFile(file_name_from));
2746 
2747   // Overwrite |dest_file|.
2748   ASSERT_TRUE(CopyFile(file_name_from, dest_file));
2749   EXPECT_TRUE(PathExists(dest_file));
2750   EXPECT_EQ(new_file_contents, ReadTextFile(dest_file));
2751 
2752   // Create another directory.
2753   FilePath dest_dir = temp_dir_.GetPath().Append(FPL("dest_dir"));
2754   ASSERT_TRUE(CreateDirectory(dest_dir));
2755   EXPECT_TRUE(DirectoryExists(dest_dir));
2756   EXPECT_TRUE(IsDirectoryEmpty(dest_dir));
2757 
2758   // Make sure CopyFile() cannot overwrite a directory.
2759   ASSERT_FALSE(CopyFile(file_name_from, dest_dir));
2760   EXPECT_TRUE(DirectoryExists(dest_dir));
2761   EXPECT_TRUE(IsDirectoryEmpty(dest_dir));
2762 }
2763 
2764 // file_util winds up using autoreleased objects on the Mac, so this needs
2765 // to be a PlatformTest.
2766 typedef PlatformTest ReadOnlyFileUtilTest;
2767 
TEST_F(ReadOnlyFileUtilTest,ContentsEqual)2768 TEST_F(ReadOnlyFileUtilTest, ContentsEqual) {
2769   FilePath data_dir;
2770   ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
2771   data_dir = data_dir.AppendASCII("file_util");
2772   ASSERT_TRUE(PathExists(data_dir));
2773 
2774   FilePath original_file =
2775       data_dir.Append(FILE_PATH_LITERAL("original.txt"));
2776   FilePath same_file =
2777       data_dir.Append(FILE_PATH_LITERAL("same.txt"));
2778   FilePath same_length_file =
2779       data_dir.Append(FILE_PATH_LITERAL("same_length.txt"));
2780   FilePath different_file =
2781       data_dir.Append(FILE_PATH_LITERAL("different.txt"));
2782   FilePath different_first_file =
2783       data_dir.Append(FILE_PATH_LITERAL("different_first.txt"));
2784   FilePath different_last_file =
2785       data_dir.Append(FILE_PATH_LITERAL("different_last.txt"));
2786   FilePath empty1_file =
2787       data_dir.Append(FILE_PATH_LITERAL("empty1.txt"));
2788   FilePath empty2_file =
2789       data_dir.Append(FILE_PATH_LITERAL("empty2.txt"));
2790   FilePath shortened_file =
2791       data_dir.Append(FILE_PATH_LITERAL("shortened.txt"));
2792   FilePath binary_file =
2793       data_dir.Append(FILE_PATH_LITERAL("binary_file.bin"));
2794   FilePath binary_file_same =
2795       data_dir.Append(FILE_PATH_LITERAL("binary_file_same.bin"));
2796   FilePath binary_file_diff =
2797       data_dir.Append(FILE_PATH_LITERAL("binary_file_diff.bin"));
2798 
2799   EXPECT_TRUE(ContentsEqual(original_file, original_file));
2800   EXPECT_TRUE(ContentsEqual(original_file, same_file));
2801   EXPECT_FALSE(ContentsEqual(original_file, same_length_file));
2802   EXPECT_FALSE(ContentsEqual(original_file, different_file));
2803   EXPECT_FALSE(ContentsEqual(FilePath(FILE_PATH_LITERAL("bogusname")),
2804                              FilePath(FILE_PATH_LITERAL("bogusname"))));
2805   EXPECT_FALSE(ContentsEqual(original_file, different_first_file));
2806   EXPECT_FALSE(ContentsEqual(original_file, different_last_file));
2807   EXPECT_TRUE(ContentsEqual(empty1_file, empty2_file));
2808   EXPECT_FALSE(ContentsEqual(original_file, shortened_file));
2809   EXPECT_FALSE(ContentsEqual(shortened_file, original_file));
2810   EXPECT_TRUE(ContentsEqual(binary_file, binary_file_same));
2811   EXPECT_FALSE(ContentsEqual(binary_file, binary_file_diff));
2812 }
2813 
TEST_F(ReadOnlyFileUtilTest,TextContentsEqual)2814 TEST_F(ReadOnlyFileUtilTest, TextContentsEqual) {
2815   FilePath data_dir;
2816   ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
2817   data_dir = data_dir.AppendASCII("file_util");
2818   ASSERT_TRUE(PathExists(data_dir));
2819 
2820   FilePath original_file =
2821       data_dir.Append(FILE_PATH_LITERAL("original.txt"));
2822   FilePath same_file =
2823       data_dir.Append(FILE_PATH_LITERAL("same.txt"));
2824   FilePath crlf_file =
2825       data_dir.Append(FILE_PATH_LITERAL("crlf.txt"));
2826   FilePath shortened_file =
2827       data_dir.Append(FILE_PATH_LITERAL("shortened.txt"));
2828   FilePath different_file =
2829       data_dir.Append(FILE_PATH_LITERAL("different.txt"));
2830   FilePath different_first_file =
2831       data_dir.Append(FILE_PATH_LITERAL("different_first.txt"));
2832   FilePath different_last_file =
2833       data_dir.Append(FILE_PATH_LITERAL("different_last.txt"));
2834   FilePath first1_file =
2835       data_dir.Append(FILE_PATH_LITERAL("first1.txt"));
2836   FilePath first2_file =
2837       data_dir.Append(FILE_PATH_LITERAL("first2.txt"));
2838   FilePath empty1_file =
2839       data_dir.Append(FILE_PATH_LITERAL("empty1.txt"));
2840   FilePath empty2_file =
2841       data_dir.Append(FILE_PATH_LITERAL("empty2.txt"));
2842   FilePath blank_line_file =
2843       data_dir.Append(FILE_PATH_LITERAL("blank_line.txt"));
2844   FilePath blank_line_crlf_file =
2845       data_dir.Append(FILE_PATH_LITERAL("blank_line_crlf.txt"));
2846 
2847   EXPECT_TRUE(TextContentsEqual(original_file, same_file));
2848   EXPECT_TRUE(TextContentsEqual(original_file, crlf_file));
2849   EXPECT_FALSE(TextContentsEqual(original_file, shortened_file));
2850   EXPECT_FALSE(TextContentsEqual(original_file, different_file));
2851   EXPECT_FALSE(TextContentsEqual(original_file, different_first_file));
2852   EXPECT_FALSE(TextContentsEqual(original_file, different_last_file));
2853   EXPECT_FALSE(TextContentsEqual(first1_file, first2_file));
2854   EXPECT_TRUE(TextContentsEqual(empty1_file, empty2_file));
2855   EXPECT_FALSE(TextContentsEqual(original_file, empty1_file));
2856   EXPECT_TRUE(TextContentsEqual(blank_line_file, blank_line_crlf_file));
2857 }
2858 
2859 // We don't need equivalent functionality outside of Windows.
2860 #if BUILDFLAG(IS_WIN)
TEST_F(FileUtilTest,CopyAndDeleteDirectoryTest)2861 TEST_F(FileUtilTest, CopyAndDeleteDirectoryTest) {
2862   // Create a directory
2863   FilePath dir_name_from = temp_dir_.GetPath().Append(
2864       FILE_PATH_LITERAL("CopyAndDelete_From_Subdir"));
2865   CreateDirectory(dir_name_from);
2866   ASSERT_TRUE(PathExists(dir_name_from));
2867 
2868   // Create a file under the directory
2869   FilePath file_name_from =
2870       dir_name_from.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt"));
2871   CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2872   ASSERT_TRUE(PathExists(file_name_from));
2873 
2874   // Move the directory by using CopyAndDeleteDirectory
2875   FilePath dir_name_to =
2876       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("CopyAndDelete_To_Subdir"));
2877   FilePath file_name_to =
2878       dir_name_to.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt"));
2879 
2880   ASSERT_FALSE(PathExists(dir_name_to));
2881 
2882   EXPECT_TRUE(internal::CopyAndDeleteDirectory(dir_name_from,
2883                                                      dir_name_to));
2884 
2885   // Check everything has been moved.
2886   EXPECT_FALSE(PathExists(dir_name_from));
2887   EXPECT_FALSE(PathExists(file_name_from));
2888   EXPECT_TRUE(PathExists(dir_name_to));
2889   EXPECT_TRUE(PathExists(file_name_to));
2890 }
2891 
TEST_F(FileUtilTest,GetTempDirTest)2892 TEST_F(FileUtilTest, GetTempDirTest) {
2893   static const TCHAR* kTmpKey = _T("TMP");
2894   static const TCHAR* kTmpValues[] = {
2895     _T(""), _T("C:"), _T("C:\\"), _T("C:\\tmp"), _T("C:\\tmp\\")
2896   };
2897   // Save the original $TMP.
2898   size_t original_tmp_size;
2899   TCHAR* original_tmp;
2900   ASSERT_EQ(0, ::_tdupenv_s(&original_tmp, &original_tmp_size, kTmpKey));
2901   // original_tmp may be NULL.
2902 
2903   for (unsigned int i = 0; i < std::size(kTmpValues); ++i) {
2904     FilePath path;
2905     ::_tputenv_s(kTmpKey, kTmpValues[i]);
2906     GetTempDir(&path);
2907     EXPECT_TRUE(path.IsAbsolute()) << "$TMP=" << kTmpValues[i] <<
2908         " result=" << path.value();
2909   }
2910 
2911   // Restore the original $TMP.
2912   if (original_tmp) {
2913     ::_tputenv_s(kTmpKey, original_tmp);
2914     free(original_tmp);
2915   } else {
2916     ::_tputenv_s(kTmpKey, _T(""));
2917   }
2918 }
2919 #endif  // BUILDFLAG(IS_WIN)
2920 
2921 // Test that files opened by OpenFile are not set up for inheritance into child
2922 // procs.
TEST_F(FileUtilTest,OpenFileNoInheritance)2923 TEST_F(FileUtilTest, OpenFileNoInheritance) {
2924   FilePath file_path(temp_dir_.GetPath().Append(FPL("a_file")));
2925 
2926 // Character set handling is leaking according to ASAN. http://crbug.com/883698
2927 #if defined(ADDRESS_SANITIZER)
2928   static constexpr const char* modes[] = {"wb", "r"};
2929 #else
2930   static constexpr const char* modes[] = {"wb", "r,ccs=UTF-8"};
2931 #endif
2932 
2933   for (const char* mode : modes) {
2934     SCOPED_TRACE(mode);
2935     ASSERT_NO_FATAL_FAILURE(CreateTextFile(file_path, L"Geepers"));
2936     FILE* file = OpenFile(file_path, mode);
2937     ASSERT_NE(nullptr, file);
2938     {
2939       ScopedClosureRunner file_closer(BindOnce(IgnoreResult(&CloseFile), file));
2940       bool is_inheritable = true;
2941       ASSERT_NO_FATAL_FAILURE(GetIsInheritable(file, &is_inheritable));
2942       EXPECT_FALSE(is_inheritable);
2943     }
2944     ASSERT_TRUE(DeleteFile(file_path));
2945   }
2946 }
2947 
TEST_F(FileUtilTest,CreateAndOpenTemporaryFileInDir)2948 TEST_F(FileUtilTest, CreateAndOpenTemporaryFileInDir) {
2949   // Create a temporary file.
2950   FilePath path;
2951   File file = CreateAndOpenTemporaryFileInDir(temp_dir_.GetPath(), &path);
2952   ASSERT_TRUE(file.IsValid());
2953   EXPECT_FALSE(path.empty());
2954 
2955   // Try to open another handle to it.
2956   File file2(path,
2957              File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WIN_SHARE_DELETE);
2958 #if BUILDFLAG(IS_WIN)
2959   // The file cannot be opened again on account of the exclusive access.
2960   EXPECT_FALSE(file2.IsValid());
2961 #else
2962   // Exclusive access isn't a thing on non-Windows platforms.
2963   EXPECT_TRUE(file2.IsValid());
2964 #endif
2965 }
2966 
TEST_F(FileUtilTest,CreateTemporaryFileTest)2967 TEST_F(FileUtilTest, CreateTemporaryFileTest) {
2968   FilePath temp_files[3];
2969   for (auto& i : temp_files) {
2970     ASSERT_TRUE(CreateTemporaryFile(&i));
2971     EXPECT_TRUE(PathExists(i));
2972     EXPECT_FALSE(DirectoryExists(i));
2973   }
2974   for (int i = 0; i < 3; i++)
2975     EXPECT_FALSE(temp_files[i] == temp_files[(i+1)%3]);
2976   for (const auto& i : temp_files)
2977     EXPECT_TRUE(DeleteFile(i));
2978 }
2979 
TEST_F(FileUtilTest,CreateAndOpenTemporaryStreamTest)2980 TEST_F(FileUtilTest, CreateAndOpenTemporaryStreamTest) {
2981   FilePath names[3];
2982   ScopedFILE fps[3];
2983   int i;
2984 
2985   // Create; make sure they are open and exist.
2986   for (i = 0; i < 3; ++i) {
2987     fps[i] = CreateAndOpenTemporaryStream(&(names[i]));
2988     ASSERT_TRUE(fps[i]);
2989     EXPECT_TRUE(PathExists(names[i]));
2990   }
2991 
2992   // Make sure all names are unique.
2993   for (i = 0; i < 3; ++i) {
2994     EXPECT_FALSE(names[i] == names[(i+1)%3]);
2995   }
2996 
2997   // Close and delete.
2998   for (i = 0; i < 3; ++i) {
2999     fps[i].reset();
3000     EXPECT_TRUE(DeleteFile(names[i]));
3001   }
3002 }
3003 
TEST_F(FileUtilTest,GetUniquePathTest)3004 TEST_F(FileUtilTest, GetUniquePathTest) {
3005   // Create a unique temp directory and use it to generate a unique file path.
3006   base::ScopedTempDir temp_dir;
3007   EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
3008   EXPECT_TRUE(temp_dir.IsValid());
3009   FilePath base_name(FILE_PATH_LITERAL("Unique_Base_Name.txt"));
3010   FilePath base_path = temp_dir.GetPath().Append(base_name);
3011   EXPECT_FALSE(PathExists(base_path));
3012 
3013   // GetUniquePath() should return unchanged path if file does not exist.
3014   EXPECT_EQ(base_path, GetUniquePath(base_path));
3015 
3016   // Create the file.
3017   {
3018     File file(base_path,
3019               File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE);
3020     EXPECT_TRUE(PathExists(base_path));
3021   }
3022 
3023   static const FilePath::CharType* const kExpectedNames[] = {
3024       FILE_PATH_LITERAL("Unique_Base_Name (1).txt"),
3025       FILE_PATH_LITERAL("Unique_Base_Name (2).txt"),
3026       FILE_PATH_LITERAL("Unique_Base_Name (3).txt"),
3027   };
3028 
3029   // Call GetUniquePath() three times against this existing file name.
3030   for (const FilePath::CharType* expected_name : kExpectedNames) {
3031     FilePath expected_path = temp_dir.GetPath().Append(expected_name);
3032     FilePath path = GetUniquePath(base_path);
3033     EXPECT_EQ(expected_path, path);
3034 
3035     // Verify that a file with this path indeed does not exist on the file
3036     // system.
3037     EXPECT_FALSE(PathExists(path));
3038 
3039     // Create the file so it exists for the next call to GetUniquePath() in the
3040     // loop.
3041     File file(path, File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE);
3042     EXPECT_TRUE(PathExists(path));
3043   }
3044 }
3045 
TEST_F(FileUtilTest,FileToFILE)3046 TEST_F(FileUtilTest, FileToFILE) {
3047   File file;
3048   FILE* stream = FileToFILE(std::move(file), "w");
3049   EXPECT_FALSE(stream);
3050 
3051   FilePath file_name = temp_dir_.GetPath().Append(FPL("The file.txt"));
3052   file = File(file_name, File::FLAG_CREATE | File::FLAG_WRITE);
3053   EXPECT_TRUE(file.IsValid());
3054 
3055   stream = FileToFILE(std::move(file), "w");
3056   EXPECT_TRUE(stream);
3057   EXPECT_FALSE(file.IsValid());
3058   EXPECT_TRUE(CloseFile(stream));
3059 }
3060 
TEST_F(FileUtilTest,FILEToFile)3061 TEST_F(FileUtilTest, FILEToFile) {
3062   ScopedFILE stream;
3063   EXPECT_FALSE(FILEToFile(stream.get()).IsValid());
3064 
3065   stream.reset(OpenFile(temp_dir_.GetPath().Append(FPL("hello.txt")), "wb+"));
3066   ASSERT_TRUE(stream);
3067   File file = FILEToFile(stream.get());
3068   EXPECT_TRUE(file.IsValid());
3069   ASSERT_EQ(fprintf(stream.get(), "there"), 5);
3070   ASSERT_EQ(fflush(stream.get()), 0);
3071   EXPECT_EQ(file.GetLength(), 5L);
3072 }
3073 
3074 #if BUILDFLAG(IS_WIN)
TEST_F(FileUtilTest,GetSecureSystemTemp)3075 TEST_F(FileUtilTest, GetSecureSystemTemp) {
3076   FilePath secure_system_temp;
3077   ASSERT_EQ(GetSecureSystemTemp(&secure_system_temp), !!::IsUserAnAdmin());
3078   if (!::IsUserAnAdmin()) {
3079     GTEST_SKIP() << "This test must be run by an admin user";
3080   }
3081 
3082   FilePath dir_windows;
3083   ASSERT_TRUE(PathService::Get(DIR_WINDOWS, &dir_windows));
3084   FilePath dir_program_files;
3085   ASSERT_TRUE(PathService::Get(DIR_PROGRAM_FILES, &dir_program_files));
3086 
3087   ASSERT_TRUE((dir_windows.AppendASCII("SystemTemp") == secure_system_temp) ||
3088               (dir_program_files == secure_system_temp));
3089 }
3090 #endif  // BUILDFLAG(IS_WIN)
3091 
TEST_F(FileUtilTest,CreateNewTempDirectoryTest)3092 TEST_F(FileUtilTest, CreateNewTempDirectoryTest) {
3093   FilePath temp_dir;
3094   ASSERT_TRUE(CreateNewTempDirectory(FilePath::StringType(), &temp_dir));
3095   EXPECT_TRUE(PathExists(temp_dir));
3096   EXPECT_TRUE(DeleteFile(temp_dir));
3097 }
3098 
3099 #if BUILDFLAG(IS_WIN)
TEST_F(FileUtilTest,TempDirectoryParentTest)3100 TEST_F(FileUtilTest, TempDirectoryParentTest) {
3101   if (!::IsUserAnAdmin()) {
3102     GTEST_SKIP() << "This test must be run by an admin user";
3103   }
3104   FilePath temp_dir;
3105   ASSERT_TRUE(CreateNewTempDirectory(FilePath::StringType(), &temp_dir));
3106   EXPECT_TRUE(PathExists(temp_dir));
3107 
3108   FilePath expected_parent_dir;
3109   if (!GetSecureSystemTemp(&expected_parent_dir)) {
3110     EXPECT_TRUE(PathService::Get(DIR_TEMP, &expected_parent_dir));
3111   }
3112   EXPECT_TRUE(expected_parent_dir.IsParent(temp_dir));
3113   EXPECT_TRUE(DeleteFile(temp_dir));
3114 }
3115 #endif  // BUILDFLAG(IS_WIN)
3116 
TEST_F(FileUtilTest,CreateNewTemporaryDirInDirTest)3117 TEST_F(FileUtilTest, CreateNewTemporaryDirInDirTest) {
3118   FilePath new_dir;
3119   ASSERT_TRUE(CreateTemporaryDirInDir(
3120       temp_dir_.GetPath(), FILE_PATH_LITERAL("CreateNewTemporaryDirInDirTest"),
3121       &new_dir));
3122   EXPECT_TRUE(PathExists(new_dir));
3123   EXPECT_TRUE(temp_dir_.GetPath().IsParent(new_dir));
3124   EXPECT_TRUE(DeleteFile(new_dir));
3125 }
3126 
3127 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
TEST_F(FileUtilTest,GetShmemTempDirTest)3128 TEST_F(FileUtilTest, GetShmemTempDirTest) {
3129   FilePath dir;
3130   EXPECT_TRUE(GetShmemTempDir(false, &dir));
3131   EXPECT_TRUE(DirectoryExists(dir));
3132 }
3133 
TEST_F(FileUtilTest,AllocateFileRegionTest_ZeroOffset)3134 TEST_F(FileUtilTest, AllocateFileRegionTest_ZeroOffset) {
3135   const int kTestFileLength = 9;
3136   char test_data[] = "test_data";
3137   FilePath file_path = temp_dir_.GetPath().Append(
3138       FILE_PATH_LITERAL("allocate_file_region_test_zero_offset"));
3139   WriteFile(file_path, test_data, kTestFileLength);
3140 
3141   File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ |
3142                            base::File::FLAG_WRITE);
3143   ASSERT_TRUE(file.IsValid());
3144   ASSERT_EQ(file.GetLength(), kTestFileLength);
3145 
3146   const int kExtendedFileLength = 23;
3147   ASSERT_TRUE(AllocateFileRegion(&file, 0, kExtendedFileLength));
3148   EXPECT_EQ(file.GetLength(), kExtendedFileLength);
3149 
3150   char data_read[32];
3151   int bytes_read = file.Read(0, data_read, kExtendedFileLength);
3152   EXPECT_EQ(bytes_read, kExtendedFileLength);
3153   for (int i = 0; i < kTestFileLength; ++i)
3154     EXPECT_EQ(test_data[i], data_read[i]);
3155   for (int i = kTestFileLength; i < kExtendedFileLength; ++i)
3156     EXPECT_EQ(0, data_read[i]);
3157 }
3158 
TEST_F(FileUtilTest,AllocateFileRegionTest_NonZeroOffset)3159 TEST_F(FileUtilTest, AllocateFileRegionTest_NonZeroOffset) {
3160   const int kTestFileLength = 9;
3161   char test_data[] = "test_data";
3162   FilePath file_path = temp_dir_.GetPath().Append(
3163       FILE_PATH_LITERAL("allocate_file_region_test_non_zero_offset"));
3164   WriteFile(file_path, test_data, kTestFileLength);
3165 
3166   File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ |
3167                            base::File::FLAG_WRITE);
3168   ASSERT_TRUE(file.IsValid());
3169   ASSERT_EQ(file.GetLength(), kTestFileLength);
3170 
3171   const int kExtensionOffset = 5;
3172   const int kExtensionSize = 10;
3173   ASSERT_TRUE(AllocateFileRegion(&file, kExtensionOffset, kExtensionSize));
3174   const int kExtendedFileLength = kExtensionOffset + kExtensionSize;
3175   EXPECT_EQ(file.GetLength(), kExtendedFileLength);
3176 
3177   char data_read[32];
3178   int bytes_read = file.Read(0, data_read, kExtendedFileLength);
3179   EXPECT_EQ(bytes_read, kExtendedFileLength);
3180   for (int i = 0; i < kTestFileLength; ++i)
3181     EXPECT_EQ(test_data[i], data_read[i]);
3182   for (int i = kTestFileLength; i < kExtendedFileLength; ++i)
3183     EXPECT_EQ(0, data_read[i]);
3184 }
3185 
TEST_F(FileUtilTest,AllocateFileRegionTest_DontTruncate)3186 TEST_F(FileUtilTest, AllocateFileRegionTest_DontTruncate) {
3187   const int kTestFileLength = 9;
3188   char test_data[] = "test_data";
3189   FilePath file_path = temp_dir_.GetPath().Append(
3190       FILE_PATH_LITERAL("allocate_file_region_test_dont_truncate"));
3191   WriteFile(file_path, test_data, kTestFileLength);
3192 
3193   File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ |
3194                            base::File::FLAG_WRITE);
3195   ASSERT_TRUE(file.IsValid());
3196   ASSERT_EQ(file.GetLength(), kTestFileLength);
3197 
3198   const int kTruncatedFileLength = 4;
3199   ASSERT_TRUE(AllocateFileRegion(&file, 0, kTruncatedFileLength));
3200   EXPECT_EQ(file.GetLength(), kTestFileLength);
3201 }
3202 #endif
3203 
TEST_F(FileUtilTest,GetHomeDirTest)3204 TEST_F(FileUtilTest, GetHomeDirTest) {
3205 #if !BUILDFLAG(IS_ANDROID)  // Not implemented on Android.
3206   // We don't actually know what the home directory is supposed to be without
3207   // calling some OS functions which would just duplicate the implementation.
3208   // So here we just test that it returns something "reasonable".
3209   FilePath home = GetHomeDir();
3210   ASSERT_FALSE(home.empty());
3211   ASSERT_TRUE(home.IsAbsolute());
3212 #endif
3213 }
3214 
TEST_F(FileUtilTest,CreateDirectoryTest)3215 TEST_F(FileUtilTest, CreateDirectoryTest) {
3216   FilePath test_root =
3217       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("create_directory_test"));
3218 #if BUILDFLAG(IS_WIN)
3219   FilePath test_path =
3220       test_root.Append(FILE_PATH_LITERAL("dir\\tree\\likely\\doesnt\\exist\\"));
3221 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
3222   FilePath test_path =
3223       test_root.Append(FILE_PATH_LITERAL("dir/tree/likely/doesnt/exist/"));
3224 #endif
3225 
3226   EXPECT_FALSE(PathExists(test_path));
3227   EXPECT_TRUE(CreateDirectory(test_path));
3228   EXPECT_TRUE(PathExists(test_path));
3229   // CreateDirectory returns true if the DirectoryExists returns true.
3230   EXPECT_TRUE(CreateDirectory(test_path));
3231 
3232   // Doesn't work to create it on top of a non-dir
3233   test_path = test_path.Append(FILE_PATH_LITERAL("foobar.txt"));
3234   EXPECT_FALSE(PathExists(test_path));
3235   CreateTextFile(test_path, L"test file");
3236   EXPECT_TRUE(PathExists(test_path));
3237   EXPECT_FALSE(CreateDirectory(test_path));
3238 
3239   EXPECT_TRUE(DeletePathRecursively(test_root));
3240   EXPECT_FALSE(PathExists(test_root));
3241   EXPECT_FALSE(PathExists(test_path));
3242 
3243   // Verify assumptions made by the Windows implementation:
3244   // 1. The current directory always exists.
3245   // 2. The root directory always exists.
3246   ASSERT_TRUE(DirectoryExists(FilePath(FilePath::kCurrentDirectory)));
3247   FilePath top_level = test_root;
3248   while (top_level != top_level.DirName()) {
3249     top_level = top_level.DirName();
3250   }
3251   ASSERT_TRUE(DirectoryExists(top_level));
3252 
3253   // Given these assumptions hold, it should be safe to
3254   // test that "creating" these directories succeeds.
3255   EXPECT_TRUE(CreateDirectory(
3256       FilePath(FilePath::kCurrentDirectory)));
3257   EXPECT_TRUE(CreateDirectory(top_level));
3258 
3259 #if BUILDFLAG(IS_WIN)
3260   FilePath invalid_drive(FILE_PATH_LITERAL("o:\\"));
3261   FilePath invalid_path =
3262       invalid_drive.Append(FILE_PATH_LITERAL("some\\inaccessible\\dir"));
3263   if (!PathExists(invalid_drive)) {
3264     EXPECT_FALSE(CreateDirectory(invalid_path));
3265   }
3266 #endif
3267 }
3268 
TEST_F(FileUtilTest,DetectDirectoryTest)3269 TEST_F(FileUtilTest, DetectDirectoryTest) {
3270   // Check a directory
3271   FilePath test_root =
3272       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("detect_directory_test"));
3273   EXPECT_FALSE(PathExists(test_root));
3274   EXPECT_TRUE(CreateDirectory(test_root));
3275   EXPECT_TRUE(PathExists(test_root));
3276   EXPECT_TRUE(DirectoryExists(test_root));
3277   // Check a file
3278   FilePath test_path =
3279       test_root.Append(FILE_PATH_LITERAL("foobar.txt"));
3280   EXPECT_FALSE(PathExists(test_path));
3281   CreateTextFile(test_path, L"test file");
3282   EXPECT_TRUE(PathExists(test_path));
3283   EXPECT_FALSE(DirectoryExists(test_path));
3284   EXPECT_TRUE(DeleteFile(test_path));
3285 
3286   EXPECT_TRUE(DeletePathRecursively(test_root));
3287 }
3288 
TEST_F(FileUtilTest,FileEnumeratorTest)3289 TEST_F(FileUtilTest, FileEnumeratorTest) {
3290   // Test an empty directory.
3291   FileEnumerator f0(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES);
3292   EXPECT_EQ(FPL(""), f0.Next().value());
3293   EXPECT_EQ(FPL(""), f0.Next().value());
3294 
3295   // Test an empty directory, non-recursively, including "..".
3296   FileEnumerator f0_dotdot(
3297       temp_dir_.GetPath(), false,
3298       FILES_AND_DIRECTORIES | FileEnumerator::INCLUDE_DOT_DOT);
3299   EXPECT_EQ(temp_dir_.GetPath().Append(FPL("..")).value(),
3300             f0_dotdot.Next().value());
3301   EXPECT_EQ(FPL(""), f0_dotdot.Next().value());
3302 
3303   // create the directories
3304   FilePath dir1 = temp_dir_.GetPath().Append(FPL("dir1"));
3305   EXPECT_TRUE(CreateDirectory(dir1));
3306   FilePath dir2 = temp_dir_.GetPath().Append(FPL("dir2"));
3307   EXPECT_TRUE(CreateDirectory(dir2));
3308   FilePath dir2inner = dir2.Append(FPL("inner"));
3309   EXPECT_TRUE(CreateDirectory(dir2inner));
3310 
3311   // create the files
3312   FilePath dir2file = dir2.Append(FPL("dir2file.txt"));
3313   CreateTextFile(dir2file, std::wstring());
3314   FilePath dir2innerfile = dir2inner.Append(FPL("innerfile.txt"));
3315   CreateTextFile(dir2innerfile, std::wstring());
3316   FilePath file1 = temp_dir_.GetPath().Append(FPL("file1.txt"));
3317   CreateTextFile(file1, std::wstring());
3318   FilePath file2_rel = dir2.Append(FilePath::kParentDirectory)
3319       .Append(FPL("file2.txt"));
3320   CreateTextFile(file2_rel, std::wstring());
3321   FilePath file2_abs = temp_dir_.GetPath().Append(FPL("file2.txt"));
3322 
3323   // Only enumerate files.
3324   FileEnumerator f1(temp_dir_.GetPath(), true, FileEnumerator::FILES);
3325   FindResultCollector c1(&f1);
3326   EXPECT_TRUE(c1.HasFile(file1));
3327   EXPECT_TRUE(c1.HasFile(file2_abs));
3328   EXPECT_TRUE(c1.HasFile(dir2file));
3329   EXPECT_TRUE(c1.HasFile(dir2innerfile));
3330   EXPECT_EQ(4, c1.size());
3331 
3332   // Only enumerate directories.
3333   FileEnumerator f2(temp_dir_.GetPath(), true, FileEnumerator::DIRECTORIES);
3334   FindResultCollector c2(&f2);
3335   EXPECT_TRUE(c2.HasFile(dir1));
3336   EXPECT_TRUE(c2.HasFile(dir2));
3337   EXPECT_TRUE(c2.HasFile(dir2inner));
3338   EXPECT_EQ(3, c2.size());
3339 
3340   // Only enumerate directories non-recursively.
3341   FileEnumerator f2_non_recursive(temp_dir_.GetPath(), false,
3342                                   FileEnumerator::DIRECTORIES);
3343   FindResultCollector c2_non_recursive(&f2_non_recursive);
3344   EXPECT_TRUE(c2_non_recursive.HasFile(dir1));
3345   EXPECT_TRUE(c2_non_recursive.HasFile(dir2));
3346   EXPECT_EQ(2, c2_non_recursive.size());
3347 
3348   // Only enumerate directories, non-recursively, including "..".
3349   FileEnumerator f2_dotdot(
3350       temp_dir_.GetPath(), false,
3351       FileEnumerator::DIRECTORIES | FileEnumerator::INCLUDE_DOT_DOT);
3352   FindResultCollector c2_dotdot(&f2_dotdot);
3353   EXPECT_TRUE(c2_dotdot.HasFile(dir1));
3354   EXPECT_TRUE(c2_dotdot.HasFile(dir2));
3355   EXPECT_TRUE(c2_dotdot.HasFile(temp_dir_.GetPath().Append(FPL(".."))));
3356   EXPECT_EQ(3, c2_dotdot.size());
3357 
3358   // Enumerate files and directories.
3359   FileEnumerator f3(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES);
3360   FindResultCollector c3(&f3);
3361   EXPECT_TRUE(c3.HasFile(dir1));
3362   EXPECT_TRUE(c3.HasFile(dir2));
3363   EXPECT_TRUE(c3.HasFile(file1));
3364   EXPECT_TRUE(c3.HasFile(file2_abs));
3365   EXPECT_TRUE(c3.HasFile(dir2file));
3366   EXPECT_TRUE(c3.HasFile(dir2inner));
3367   EXPECT_TRUE(c3.HasFile(dir2innerfile));
3368   EXPECT_EQ(7, c3.size());
3369 
3370   // Non-recursive operation.
3371   FileEnumerator f4(temp_dir_.GetPath(), false, FILES_AND_DIRECTORIES);
3372   FindResultCollector c4(&f4);
3373   EXPECT_TRUE(c4.HasFile(dir2));
3374   EXPECT_TRUE(c4.HasFile(dir2));
3375   EXPECT_TRUE(c4.HasFile(file1));
3376   EXPECT_TRUE(c4.HasFile(file2_abs));
3377   EXPECT_EQ(4, c4.size());
3378 
3379   // Enumerate with a pattern.
3380   FileEnumerator f5(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES,
3381                     FPL("dir*"));
3382   FindResultCollector c5(&f5);
3383   EXPECT_TRUE(c5.HasFile(dir1));
3384   EXPECT_TRUE(c5.HasFile(dir2));
3385   EXPECT_TRUE(c5.HasFile(dir2file));
3386   EXPECT_TRUE(c5.HasFile(dir2inner));
3387   EXPECT_TRUE(c5.HasFile(dir2innerfile));
3388   EXPECT_EQ(5, c5.size());
3389 
3390 #if BUILDFLAG(IS_WIN)
3391   {
3392     // Make dir1 point to dir2.
3393     auto reparse_point = test::FilePathReparsePoint::Create(dir1, dir2);
3394     EXPECT_TRUE(reparse_point.has_value());
3395 
3396     // There can be a delay for the enumeration code to see the change on
3397     // the file system so skip this test for XP.
3398     // Enumerate the reparse point.
3399     FileEnumerator f6(dir1, true, FILES_AND_DIRECTORIES);
3400     FindResultCollector c6(&f6);
3401     FilePath inner2 = dir1.Append(FPL("inner"));
3402     EXPECT_TRUE(c6.HasFile(inner2));
3403     EXPECT_TRUE(c6.HasFile(inner2.Append(FPL("innerfile.txt"))));
3404     EXPECT_TRUE(c6.HasFile(dir1.Append(FPL("dir2file.txt"))));
3405     EXPECT_EQ(3, c6.size());
3406 
3407     // No changes for non recursive operation.
3408     FileEnumerator f7(temp_dir_.GetPath(), false, FILES_AND_DIRECTORIES);
3409     FindResultCollector c7(&f7);
3410     EXPECT_TRUE(c7.HasFile(dir2));
3411     EXPECT_TRUE(c7.HasFile(dir2));
3412     EXPECT_TRUE(c7.HasFile(file1));
3413     EXPECT_TRUE(c7.HasFile(file2_abs));
3414     EXPECT_EQ(4, c7.size());
3415 
3416     // Should not enumerate inside dir1 when using recursion.
3417     FileEnumerator f8(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES);
3418     FindResultCollector c8(&f8);
3419     EXPECT_TRUE(c8.HasFile(dir1));
3420     EXPECT_TRUE(c8.HasFile(dir2));
3421     EXPECT_TRUE(c8.HasFile(file1));
3422     EXPECT_TRUE(c8.HasFile(file2_abs));
3423     EXPECT_TRUE(c8.HasFile(dir2file));
3424     EXPECT_TRUE(c8.HasFile(dir2inner));
3425     EXPECT_TRUE(c8.HasFile(dir2innerfile));
3426     EXPECT_EQ(7, c8.size());
3427   }
3428 #endif
3429 
3430   // Make sure the destructor closes the find handle while in the middle of a
3431   // query to allow TearDown to delete the directory.
3432   FileEnumerator f9(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES);
3433   EXPECT_FALSE(f9.Next().value().empty());  // Should have found something
3434                                             // (we don't care what).
3435 }
3436 
TEST_F(FileUtilTest,AppendToFile)3437 TEST_F(FileUtilTest, AppendToFile) {
3438   FilePath data_dir =
3439       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("FilePathTest"));
3440 
3441   // Create a fresh, empty copy of this directory.
3442   if (PathExists(data_dir)) {
3443     ASSERT_TRUE(DeletePathRecursively(data_dir));
3444   }
3445   ASSERT_TRUE(CreateDirectory(data_dir));
3446 
3447   // Create a fresh, empty copy of this directory.
3448   if (PathExists(data_dir)) {
3449     ASSERT_TRUE(DeletePathRecursively(data_dir));
3450   }
3451   ASSERT_TRUE(CreateDirectory(data_dir));
3452   FilePath foobar(data_dir.Append(FILE_PATH_LITERAL("foobar.txt")));
3453 
3454   std::string data("hello");
3455   EXPECT_FALSE(AppendToFile(foobar, data));
3456   EXPECT_TRUE(WriteFile(foobar, data));
3457   EXPECT_TRUE(AppendToFile(foobar, data));
3458 
3459   const std::wstring read_content = ReadTextFile(foobar);
3460   EXPECT_EQ(L"hellohello", read_content);
3461 }
3462 
TEST_F(FileUtilTest,ReadFile)3463 TEST_F(FileUtilTest, ReadFile) {
3464   // Create a test file to be read.
3465   const std::string kTestData("The quick brown fox jumps over the lazy dog.");
3466   FilePath file_path =
3467       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("ReadFileTest"));
3468 
3469   ASSERT_TRUE(WriteFile(file_path, kTestData));
3470 
3471   // Make buffers with various size.
3472   std::vector<char> small_buffer(kTestData.size() / 2);
3473   std::vector<char> exact_buffer(kTestData.size());
3474   std::vector<char> large_buffer(kTestData.size() * 2);
3475 
3476   // Read the file with smaller buffer.
3477   EXPECT_EQ(ReadFile(file_path, small_buffer), small_buffer.size());
3478   EXPECT_EQ(
3479       std::string(kTestData.begin(), kTestData.begin() + small_buffer.size()),
3480       std::string(small_buffer.begin(), small_buffer.end()));
3481 
3482   // Read the file with buffer which have exactly same size.
3483   EXPECT_EQ(ReadFile(file_path, exact_buffer), kTestData.size());
3484   EXPECT_EQ(kTestData, std::string(exact_buffer.begin(), exact_buffer.end()));
3485 
3486   // Read the file with larger buffer.
3487   EXPECT_EQ(ReadFile(file_path, large_buffer), kTestData.size());
3488   EXPECT_EQ(kTestData, std::string(large_buffer.begin(),
3489                                    large_buffer.begin() + kTestData.size()));
3490 
3491   // Make sure the read fails if the file doesn't exist.
3492   FilePath file_path_not_exist =
3493       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("ReadFileNotExistTest"));
3494   EXPECT_EQ(ReadFile(file_path_not_exist, exact_buffer), std::nullopt);
3495 }
3496 
TEST_F(FileUtilTest,ReadFileToBytes)3497 TEST_F(FileUtilTest, ReadFileToBytes) {
3498   const std::vector<uint8_t> kTestData = {'0', '1', '2', '3'};
3499 
3500   FilePath file_path =
3501       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("ReadFileToStringTest"));
3502   FilePath file_path_dangerous =
3503       temp_dir_.GetPath()
3504           .Append(FILE_PATH_LITERAL(".."))
3505           .Append(temp_dir_.GetPath().BaseName())
3506           .Append(FILE_PATH_LITERAL("ReadFileToStringTest"));
3507 
3508   // Create test file.
3509   ASSERT_TRUE(WriteFile(file_path, kTestData));
3510 
3511   std::optional<std::vector<uint8_t>> bytes = ReadFileToBytes(file_path);
3512   ASSERT_TRUE(bytes.has_value());
3513   EXPECT_EQ(kTestData, bytes);
3514 
3515   // Write empty file.
3516   ASSERT_TRUE(WriteFile(file_path, ""));
3517   bytes = ReadFileToBytes(file_path);
3518   ASSERT_TRUE(bytes.has_value());
3519   EXPECT_TRUE(bytes->empty());
3520 
3521   ASSERT_FALSE(ReadFileToBytes(file_path_dangerous));
3522 }
3523 
TEST_F(FileUtilTest,ReadFileToString)3524 TEST_F(FileUtilTest, ReadFileToString) {
3525   const char kTestData[] = "0123";
3526   std::string data;
3527 
3528   FilePath file_path =
3529       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("ReadFileToStringTest"));
3530   FilePath file_path_dangerous =
3531       temp_dir_.GetPath()
3532           .Append(FILE_PATH_LITERAL(".."))
3533           .Append(temp_dir_.GetPath().BaseName())
3534           .Append(FILE_PATH_LITERAL("ReadFileToStringTest"));
3535 
3536   // Create test file.
3537   ASSERT_TRUE(WriteFile(file_path, kTestData));
3538 
3539   EXPECT_TRUE(ReadFileToString(file_path, &data));
3540   EXPECT_EQ(kTestData, data);
3541 
3542   data = "temp";
3543   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 0));
3544   EXPECT_EQ(0u, data.length());
3545 
3546   data = "temp";
3547   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 2));
3548   EXPECT_EQ("01", data);
3549 
3550   data = "temp";
3551   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 3));
3552   EXPECT_EQ("012", data);
3553 
3554   data = "temp";
3555   EXPECT_TRUE(ReadFileToStringWithMaxSize(file_path, &data, 4));
3556   EXPECT_EQ("0123", data);
3557 
3558   data = "temp";
3559   EXPECT_TRUE(ReadFileToStringWithMaxSize(file_path, &data, 6));
3560   EXPECT_EQ("0123", data);
3561 
3562   EXPECT_TRUE(ReadFileToStringWithMaxSize(file_path, nullptr, 6));
3563 
3564   EXPECT_TRUE(ReadFileToString(file_path, nullptr));
3565 
3566   data = "temp";
3567   EXPECT_FALSE(ReadFileToString(file_path_dangerous, &data));
3568   EXPECT_EQ(0u, data.length());
3569 
3570   // Delete test file.
3571   EXPECT_TRUE(DeleteFile(file_path));
3572 
3573   data = "temp";
3574   EXPECT_FALSE(ReadFileToString(file_path, &data));
3575   EXPECT_EQ(0u, data.length());
3576 
3577   data = "temp";
3578   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 6));
3579   EXPECT_EQ(0u, data.length());
3580 }
3581 
3582 #if !BUILDFLAG(IS_WIN)
TEST_F(FileUtilTest,ReadFileToStringWithUnknownFileSize)3583 TEST_F(FileUtilTest, ReadFileToStringWithUnknownFileSize) {
3584 #if BUILDFLAG(IS_FUCHSIA)
3585   test::TaskEnvironment task_environment;
3586   auto dev_zero = ScopedDevZero::Get();
3587   ASSERT_TRUE(dev_zero);
3588 #endif
3589   FilePath file_path("/dev/zero");
3590   std::string data = "temp";
3591 
3592   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 0));
3593   EXPECT_EQ(0u, data.length());
3594 
3595   data = "temp";
3596   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 2));
3597   EXPECT_EQ(std::string(2, '\0'), data);
3598 
3599   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, nullptr, 6));
3600 
3601   // Read more than buffer size.
3602   data = "temp";
3603   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, kLargeFileSize));
3604   EXPECT_EQ(kLargeFileSize, data.length());
3605   EXPECT_EQ(std::string(kLargeFileSize, '\0'), data);
3606 
3607   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, nullptr, kLargeFileSize));
3608 }
3609 #endif  // !BUILDFLAG(IS_WIN)
3610 
3611 #if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_FUCHSIA) && \
3612     !BUILDFLAG(IS_IOS)
3613 #define ChildMain WriteToPipeChildMain
3614 #define ChildMainString "WriteToPipeChildMain"
3615 
MULTIPROCESS_TEST_MAIN(ChildMain)3616 MULTIPROCESS_TEST_MAIN(ChildMain) {
3617   const char kTestData[] = "0123";
3618   CommandLine* command_line = CommandLine::ForCurrentProcess();
3619   const FilePath pipe_path = command_line->GetSwitchValuePath("pipe-path");
3620 
3621   int fd = open(pipe_path.value().c_str(), O_WRONLY);
3622   CHECK_NE(-1, fd);
3623   size_t written = 0;
3624   while (written < strlen(kTestData)) {
3625     ssize_t res = write(fd, kTestData + written, strlen(kTestData) - written);
3626     if (res == -1)
3627       break;
3628     written += res;
3629   }
3630   CHECK_EQ(strlen(kTestData), written);
3631   CHECK_EQ(0, close(fd));
3632   return 0;
3633 }
3634 
3635 #define MoreThanBufferSizeChildMain WriteToPipeMoreThanBufferSizeChildMain
3636 #define MoreThanBufferSizeChildMainString \
3637   "WriteToPipeMoreThanBufferSizeChildMain"
3638 
MULTIPROCESS_TEST_MAIN(MoreThanBufferSizeChildMain)3639 MULTIPROCESS_TEST_MAIN(MoreThanBufferSizeChildMain) {
3640   std::string data(kLargeFileSize, 'c');
3641   CommandLine* command_line = CommandLine::ForCurrentProcess();
3642   const FilePath pipe_path = command_line->GetSwitchValuePath("pipe-path");
3643 
3644   int fd = open(pipe_path.value().c_str(), O_WRONLY);
3645   CHECK_NE(-1, fd);
3646 
3647   size_t written = 0;
3648   while (written < data.size()) {
3649     ssize_t res = write(fd, data.c_str() + written, data.size() - written);
3650     if (res == -1) {
3651       // We are unable to write because reading process has already read
3652       // requested number of bytes and closed pipe.
3653       break;
3654     }
3655     written += res;
3656   }
3657   CHECK_EQ(0, close(fd));
3658   return 0;
3659 }
3660 
TEST_F(FileUtilTest,ReadFileToStringWithNamedPipe)3661 TEST_F(FileUtilTest, ReadFileToStringWithNamedPipe) {
3662   FilePath pipe_path =
3663       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("test_pipe"));
3664   ASSERT_EQ(0, mkfifo(pipe_path.value().c_str(), 0600));
3665 
3666   CommandLine child_command_line(GetMultiProcessTestChildBaseCommandLine());
3667   child_command_line.AppendSwitchPath("pipe-path", pipe_path);
3668 
3669   {
3670     Process child_process = SpawnMultiProcessTestChild(
3671         ChildMainString, child_command_line, LaunchOptions());
3672     ASSERT_TRUE(child_process.IsValid());
3673 
3674     std::string data = "temp";
3675     EXPECT_FALSE(ReadFileToStringWithMaxSize(pipe_path, &data, 2));
3676     EXPECT_EQ("01", data);
3677 
3678     int rv = -1;
3679     ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3680         child_process, TestTimeouts::action_timeout(), &rv));
3681     ASSERT_EQ(0, rv);
3682   }
3683   {
3684     Process child_process = SpawnMultiProcessTestChild(
3685         ChildMainString, child_command_line, LaunchOptions());
3686     ASSERT_TRUE(child_process.IsValid());
3687 
3688     std::string data = "temp";
3689     EXPECT_TRUE(ReadFileToStringWithMaxSize(pipe_path, &data, 6));
3690     EXPECT_EQ("0123", data);
3691 
3692     int rv = -1;
3693     ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3694         child_process, TestTimeouts::action_timeout(), &rv));
3695     ASSERT_EQ(0, rv);
3696   }
3697   {
3698     Process child_process = SpawnMultiProcessTestChild(
3699         MoreThanBufferSizeChildMainString, child_command_line, LaunchOptions());
3700     ASSERT_TRUE(child_process.IsValid());
3701 
3702     std::string data = "temp";
3703     EXPECT_FALSE(ReadFileToStringWithMaxSize(pipe_path, &data, 6));
3704     EXPECT_EQ("cccccc", data);
3705 
3706     int rv = -1;
3707     ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3708         child_process, TestTimeouts::action_timeout(), &rv));
3709     ASSERT_EQ(0, rv);
3710   }
3711   {
3712     Process child_process = SpawnMultiProcessTestChild(
3713         MoreThanBufferSizeChildMainString, child_command_line, LaunchOptions());
3714     ASSERT_TRUE(child_process.IsValid());
3715 
3716     std::string data = "temp";
3717     EXPECT_FALSE(
3718         ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize - 1));
3719     EXPECT_EQ(std::string(kLargeFileSize - 1, 'c'), data);
3720 
3721     int rv = -1;
3722     ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3723         child_process, TestTimeouts::action_timeout(), &rv));
3724     ASSERT_EQ(0, rv);
3725   }
3726   {
3727     Process child_process = SpawnMultiProcessTestChild(
3728         MoreThanBufferSizeChildMainString, child_command_line, LaunchOptions());
3729     ASSERT_TRUE(child_process.IsValid());
3730 
3731     std::string data = "temp";
3732     EXPECT_TRUE(ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize));
3733     EXPECT_EQ(std::string(kLargeFileSize, 'c'), data);
3734 
3735     int rv = -1;
3736     ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3737         child_process, TestTimeouts::action_timeout(), &rv));
3738     ASSERT_EQ(0, rv);
3739   }
3740   {
3741     Process child_process = SpawnMultiProcessTestChild(
3742         MoreThanBufferSizeChildMainString, child_command_line, LaunchOptions());
3743     ASSERT_TRUE(child_process.IsValid());
3744 
3745     std::string data = "temp";
3746     EXPECT_TRUE(
3747         ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize * 5));
3748     EXPECT_EQ(std::string(kLargeFileSize, 'c'), data);
3749 
3750     int rv = -1;
3751     ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3752         child_process, TestTimeouts::action_timeout(), &rv));
3753     ASSERT_EQ(0, rv);
3754   }
3755 
3756   ASSERT_EQ(0, unlink(pipe_path.value().c_str()));
3757 }
3758 #endif  // !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_FUCHSIA)
3759         // && !BUILDFLAG(IS_IOS)
3760 
3761 #if BUILDFLAG(IS_WIN)
3762 #define ChildMain WriteToPipeChildMain
3763 #define ChildMainString "WriteToPipeChildMain"
3764 
MULTIPROCESS_TEST_MAIN(ChildMain)3765 MULTIPROCESS_TEST_MAIN(ChildMain) {
3766   const char kTestData[] = "0123";
3767   CommandLine* command_line = CommandLine::ForCurrentProcess();
3768   const FilePath pipe_path = command_line->GetSwitchValuePath("pipe-path");
3769   std::string switch_string = command_line->GetSwitchValueASCII("sync_event");
3770   EXPECT_FALSE(switch_string.empty());
3771   unsigned int switch_uint = 0;
3772   EXPECT_TRUE(StringToUint(switch_string, &switch_uint));
3773   win::ScopedHandle sync_event(win::Uint32ToHandle(switch_uint));
3774 
3775   HANDLE ph = CreateNamedPipe(pipe_path.value().c_str(), PIPE_ACCESS_OUTBOUND,
3776                               PIPE_WAIT, 1, 0, 0, 0, NULL);
3777   EXPECT_NE(ph, INVALID_HANDLE_VALUE);
3778   EXPECT_TRUE(SetEvent(sync_event.get()));
3779   if (!::ConnectNamedPipe(ph, /*lpOverlapped=*/nullptr)) {
3780     // ERROR_PIPE_CONNECTED means that the other side has already connected.
3781     auto error = ::GetLastError();
3782     EXPECT_EQ(error, DWORD{ERROR_PIPE_CONNECTED});
3783   }
3784 
3785   DWORD written;
3786   EXPECT_TRUE(::WriteFile(ph, kTestData, strlen(kTestData), &written, NULL));
3787   EXPECT_EQ(strlen(kTestData), written);
3788   CloseHandle(ph);
3789   return 0;
3790 }
3791 
3792 #define MoreThanBufferSizeChildMain WriteToPipeMoreThanBufferSizeChildMain
3793 #define MoreThanBufferSizeChildMainString \
3794   "WriteToPipeMoreThanBufferSizeChildMain"
3795 
MULTIPROCESS_TEST_MAIN(MoreThanBufferSizeChildMain)3796 MULTIPROCESS_TEST_MAIN(MoreThanBufferSizeChildMain) {
3797   std::string data(kLargeFileSize, 'c');
3798   CommandLine* command_line = CommandLine::ForCurrentProcess();
3799   const FilePath pipe_path = command_line->GetSwitchValuePath("pipe-path");
3800   std::string switch_string = command_line->GetSwitchValueASCII("sync_event");
3801   EXPECT_FALSE(switch_string.empty());
3802   unsigned int switch_uint = 0;
3803   EXPECT_TRUE(StringToUint(switch_string, &switch_uint));
3804   win::ScopedHandle sync_event(win::Uint32ToHandle(switch_uint));
3805 
3806   HANDLE ph = CreateNamedPipe(pipe_path.value().c_str(), PIPE_ACCESS_OUTBOUND,
3807                               PIPE_WAIT, 1, data.size(), data.size(), 0, NULL);
3808   EXPECT_NE(ph, INVALID_HANDLE_VALUE);
3809   EXPECT_TRUE(SetEvent(sync_event.get()));
3810   if (!::ConnectNamedPipe(ph, /*lpOverlapped=*/nullptr)) {
3811     // ERROR_PIPE_CONNECTED means that the other side has already connected.
3812     auto error = ::GetLastError();
3813     EXPECT_EQ(error, DWORD{ERROR_PIPE_CONNECTED});
3814   }
3815 
3816   DWORD written;
3817   EXPECT_TRUE(::WriteFile(ph, data.c_str(), data.size(), &written, NULL));
3818   EXPECT_EQ(data.size(), written);
3819   CloseHandle(ph);
3820   return 0;
3821 }
3822 
TEST_F(FileUtilTest,ReadFileToStringWithNamedPipe)3823 TEST_F(FileUtilTest, ReadFileToStringWithNamedPipe) {
3824   FilePath pipe_path(FILE_PATH_LITERAL("\\\\.\\pipe\\test_pipe"));
3825   win::ScopedHandle sync_event(CreateEvent(0, false, false, nullptr));
3826 
3827   CommandLine child_command_line(GetMultiProcessTestChildBaseCommandLine());
3828   child_command_line.AppendSwitchPath("pipe-path", pipe_path);
3829   child_command_line.AppendSwitchASCII(
3830       "sync_event", NumberToString(win::HandleToUint32(sync_event.get())));
3831 
3832   LaunchOptions options;
3833   options.handles_to_inherit.push_back(sync_event.get());
3834 
3835   {
3836     Process child_process = SpawnMultiProcessTestChild(
3837         ChildMainString, child_command_line, options);
3838     ASSERT_TRUE(child_process.IsValid());
3839     // Wait for pipe creation in child process.
3840     EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.get(), INFINITE));
3841 
3842     std::string data = "temp";
3843     EXPECT_FALSE(ReadFileToStringWithMaxSize(pipe_path, &data, 2));
3844     EXPECT_EQ("01", data);
3845 
3846     int rv = -1;
3847     ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3848         child_process, TestTimeouts::action_timeout(), &rv));
3849     ASSERT_EQ(0, rv);
3850   }
3851   {
3852     Process child_process = SpawnMultiProcessTestChild(
3853         ChildMainString, child_command_line, options);
3854     ASSERT_TRUE(child_process.IsValid());
3855     // Wait for pipe creation in child process.
3856     EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.get(), INFINITE));
3857 
3858     std::string data = "temp";
3859     EXPECT_TRUE(ReadFileToStringWithMaxSize(pipe_path, &data, 6));
3860     EXPECT_EQ("0123", data);
3861 
3862     int rv = -1;
3863     ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3864         child_process, TestTimeouts::action_timeout(), &rv));
3865     ASSERT_EQ(0, rv);
3866   }
3867   {
3868     Process child_process = SpawnMultiProcessTestChild(
3869         MoreThanBufferSizeChildMainString, child_command_line, options);
3870     ASSERT_TRUE(child_process.IsValid());
3871     // Wait for pipe creation in child process.
3872     EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.get(), INFINITE));
3873 
3874     std::string data = "temp";
3875     EXPECT_FALSE(ReadFileToStringWithMaxSize(pipe_path, &data, 6));
3876     EXPECT_EQ("cccccc", data);
3877 
3878     int rv = -1;
3879     ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3880         child_process, TestTimeouts::action_timeout(), &rv));
3881     ASSERT_EQ(0, rv);
3882   }
3883   {
3884     Process child_process = SpawnMultiProcessTestChild(
3885         MoreThanBufferSizeChildMainString, child_command_line, options);
3886     ASSERT_TRUE(child_process.IsValid());
3887     // Wait for pipe creation in child process.
3888     EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.get(), INFINITE));
3889 
3890     std::string data = "temp";
3891     EXPECT_FALSE(
3892         ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize - 1));
3893     EXPECT_EQ(std::string(kLargeFileSize - 1, 'c'), data);
3894 
3895     int rv = -1;
3896     ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3897         child_process, TestTimeouts::action_timeout(), &rv));
3898     ASSERT_EQ(0, rv);
3899   }
3900   {
3901     Process child_process = SpawnMultiProcessTestChild(
3902         MoreThanBufferSizeChildMainString, child_command_line, options);
3903     ASSERT_TRUE(child_process.IsValid());
3904     // Wait for pipe creation in child process.
3905     EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.get(), INFINITE));
3906 
3907     std::string data = "temp";
3908     EXPECT_TRUE(ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize));
3909     EXPECT_EQ(std::string(kLargeFileSize, 'c'), data);
3910 
3911     int rv = -1;
3912     ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3913         child_process, TestTimeouts::action_timeout(), &rv));
3914     ASSERT_EQ(0, rv);
3915   }
3916   {
3917     Process child_process = SpawnMultiProcessTestChild(
3918         MoreThanBufferSizeChildMainString, child_command_line, options);
3919     ASSERT_TRUE(child_process.IsValid());
3920     // Wait for pipe creation in child process.
3921     EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.get(), INFINITE));
3922 
3923     std::string data = "temp";
3924     EXPECT_TRUE(
3925         ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize * 5));
3926     EXPECT_EQ(std::string(kLargeFileSize, 'c'), data);
3927 
3928     int rv = -1;
3929     ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3930         child_process, TestTimeouts::action_timeout(), &rv));
3931     ASSERT_EQ(0, rv);
3932   }
3933 }
3934 #endif  // BUILDFLAG(IS_WIN)
3935 
3936 #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
TEST_F(FileUtilTest,ReadFileToStringWithProcFileSystem)3937 TEST_F(FileUtilTest, ReadFileToStringWithProcFileSystem) {
3938   FilePath file_path("/proc/cpuinfo");
3939   std::string data = "temp";
3940 
3941   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 0));
3942   EXPECT_EQ(0u, data.length());
3943 
3944   data = "temp";
3945   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 2));
3946   EXPECT_TRUE(EqualsCaseInsensitiveASCII("pr", data));
3947 
3948   data = "temp";
3949   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 4));
3950   EXPECT_TRUE(EqualsCaseInsensitiveASCII("proc", data));
3951 
3952   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, nullptr, 4));
3953 }
3954 #endif  // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
3955 
TEST_F(FileUtilTest,ReadFileToStringWithLargeFile)3956 TEST_F(FileUtilTest, ReadFileToStringWithLargeFile) {
3957   std::string data(kLargeFileSize, 'c');
3958 
3959   FilePath file_path =
3960       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("ReadFileToStringTest"));
3961 
3962   // Create test file.
3963   ASSERT_TRUE(WriteFile(file_path, data));
3964 
3965   std::string actual_data = "temp";
3966   EXPECT_TRUE(ReadFileToString(file_path, &actual_data));
3967   EXPECT_EQ(data, actual_data);
3968 
3969   actual_data = "temp";
3970   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &actual_data, 0));
3971   EXPECT_EQ(0u, actual_data.length());
3972 
3973   // Read more than buffer size.
3974   actual_data = "temp";
3975   EXPECT_FALSE(
3976       ReadFileToStringWithMaxSize(file_path, &actual_data, kLargeFileSize - 1));
3977   EXPECT_EQ(std::string(kLargeFileSize - 1, 'c'), actual_data);
3978 }
3979 
TEST_F(FileUtilTest,ReadStreamToString)3980 TEST_F(FileUtilTest, ReadStreamToString) {
3981   ScopedFILE stream(
3982       OpenFile(temp_dir_.GetPath().Append(FPL("hello.txt")), "wb+"));
3983   ASSERT_TRUE(stream);
3984   File file = FILEToFile(stream.get());
3985   ASSERT_TRUE(file.IsValid());
3986   ASSERT_EQ(fprintf(stream.get(), "there"), 5);
3987   ASSERT_EQ(fflush(stream.get()), 0);
3988 
3989   std::string contents;
3990   EXPECT_TRUE(ReadStreamToString(stream.get(), &contents));
3991   EXPECT_EQ(contents, std::string("there"));
3992 }
3993 
3994 #if BUILDFLAG(IS_POSIX)
TEST_F(FileUtilTest,ReadStreamToString_ZeroLengthFile)3995 TEST_F(FileUtilTest, ReadStreamToString_ZeroLengthFile) {
3996   Thread write_thread("write thread");
3997   ASSERT_TRUE(write_thread.Start());
3998 
3999   const size_t kSizes[] = {0, 1, 4095, 4096, 4097, 65535, 65536, 65537};
4000 
4001   for (size_t size : kSizes) {
4002     ScopedFD read_fd, write_fd;
4003     // Pipes have a length of zero when stat()'d.
4004     ASSERT_TRUE(CreatePipe(&read_fd, &write_fd, false /* non_blocking */));
4005 
4006     std::string random_data;
4007     if (size > 0) {
4008       random_data = RandBytesAsString(size);
4009     }
4010     EXPECT_EQ(size, random_data.size());
4011     write_thread.task_runner()->PostTask(
4012         FROM_HERE,
4013         BindLambdaForTesting([random_data, write_fd = std::move(write_fd)]() {
4014           ASSERT_TRUE(WriteFileDescriptor(write_fd.get(), random_data));
4015         }));
4016 
4017     ScopedFILE read_file(fdopen(read_fd.release(), "r"));
4018     ASSERT_TRUE(read_file);
4019 
4020     std::string contents;
4021     EXPECT_TRUE(ReadStreamToString(read_file.get(), &contents));
4022     EXPECT_EQ(contents, random_data);
4023   }
4024 }
4025 #endif
4026 
TEST_F(FileUtilTest,ReadStreamToStringWithMaxSize)4027 TEST_F(FileUtilTest, ReadStreamToStringWithMaxSize) {
4028   ScopedFILE stream(
4029       OpenFile(temp_dir_.GetPath().Append(FPL("hello.txt")), "wb+"));
4030   ASSERT_TRUE(stream);
4031   File file = FILEToFile(stream.get());
4032   ASSERT_TRUE(file.IsValid());
4033   ASSERT_EQ(fprintf(stream.get(), "there"), 5);
4034   ASSERT_EQ(fflush(stream.get()), 0);
4035 
4036   std::string contents;
4037   EXPECT_FALSE(ReadStreamToStringWithMaxSize(stream.get(), 2, &contents));
4038 }
4039 
TEST_F(FileUtilTest,ReadStreamToStringNullStream)4040 TEST_F(FileUtilTest, ReadStreamToStringNullStream) {
4041   std::string contents;
4042   EXPECT_FALSE(ReadStreamToString(nullptr, &contents));
4043 }
4044 
TEST_F(FileUtilTest,TouchFile)4045 TEST_F(FileUtilTest, TouchFile) {
4046   FilePath data_dir =
4047       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("FilePathTest"));
4048 
4049   // Create a fresh, empty copy of this directory.
4050   if (PathExists(data_dir)) {
4051     ASSERT_TRUE(DeletePathRecursively(data_dir));
4052   }
4053   ASSERT_TRUE(CreateDirectory(data_dir));
4054 
4055   FilePath foobar(data_dir.Append(FILE_PATH_LITERAL("foobar.txt")));
4056   std::string data("hello");
4057   ASSERT_TRUE(WriteFile(foobar, data));
4058 
4059   Time access_time;
4060   // This timestamp is divisible by one day (in local timezone),
4061   // to make it work on FAT too.
4062   ASSERT_TRUE(Time::FromString("Wed, 16 Nov 1994, 00:00:00",
4063                                &access_time));
4064 
4065   Time modification_time;
4066   // Note that this timestamp is divisible by two (seconds) - FAT stores
4067   // modification times with 2s resolution.
4068   ASSERT_TRUE(Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT",
4069               &modification_time));
4070 
4071   ASSERT_TRUE(TouchFile(foobar, access_time, modification_time));
4072   File::Info file_info;
4073   ASSERT_TRUE(GetFileInfo(foobar, &file_info));
4074 #if !BUILDFLAG(IS_FUCHSIA)
4075   // Access time is not supported on Fuchsia, see https://crbug.com/735233.
4076   EXPECT_EQ(access_time.ToInternalValue(),
4077             file_info.last_accessed.ToInternalValue());
4078 #endif
4079   EXPECT_EQ(modification_time.ToInternalValue(),
4080             file_info.last_modified.ToInternalValue());
4081 }
4082 
TEST_F(FileUtilTest,WriteFileSpanVariant)4083 TEST_F(FileUtilTest, WriteFileSpanVariant) {
4084   FilePath empty_file =
4085       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("empty_file"));
4086   ASSERT_FALSE(PathExists(empty_file));
4087   EXPECT_TRUE(WriteFile(empty_file, base::span<const uint8_t>()));
4088   EXPECT_TRUE(PathExists(empty_file));
4089 
4090   std::string data = "not empty";
4091   EXPECT_TRUE(ReadFileToString(empty_file, &data));
4092   EXPECT_TRUE(data.empty());
4093 
4094   FilePath write_span_file =
4095       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("write_span_file"));
4096   ASSERT_FALSE(PathExists(write_span_file));
4097   static constexpr uint8_t kInput[] = {'h', 'e', 'l', 'l', 'o'};
4098   EXPECT_TRUE(WriteFile(write_span_file, kInput));
4099   EXPECT_TRUE(PathExists(write_span_file));
4100 
4101   data.clear();
4102   EXPECT_TRUE(ReadFileToString(write_span_file, &data));
4103   EXPECT_EQ("hello", data);
4104 }
4105 
TEST_F(FileUtilTest,WriteFileStringVariant)4106 TEST_F(FileUtilTest, WriteFileStringVariant) {
4107   FilePath empty_file =
4108       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("empty_file"));
4109   ASSERT_FALSE(PathExists(empty_file));
4110   EXPECT_TRUE(WriteFile(empty_file, ""));
4111   EXPECT_TRUE(PathExists(empty_file));
4112 
4113   std::string data = "not empty";
4114   EXPECT_TRUE(ReadFileToString(empty_file, &data));
4115   EXPECT_TRUE(data.empty());
4116 
4117   FilePath write_span_file =
4118       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("write_string_file"));
4119   ASSERT_FALSE(PathExists(write_span_file));
4120   EXPECT_TRUE(WriteFile(write_span_file, "world"));
4121   EXPECT_TRUE(PathExists(write_span_file));
4122 
4123   data.clear();
4124   EXPECT_TRUE(ReadFileToString(write_span_file, &data));
4125   EXPECT_EQ("world", data);
4126 }
4127 
TEST_F(FileUtilTest,IsDirectoryEmpty)4128 TEST_F(FileUtilTest, IsDirectoryEmpty) {
4129   FilePath empty_dir =
4130       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("EmptyDir"));
4131 
4132   ASSERT_FALSE(PathExists(empty_dir));
4133 
4134   ASSERT_TRUE(CreateDirectory(empty_dir));
4135 
4136   EXPECT_TRUE(IsDirectoryEmpty(empty_dir));
4137 
4138   FilePath foo(empty_dir.Append(FILE_PATH_LITERAL("foo.txt")));
4139   std::string bar("baz");
4140   ASSERT_TRUE(WriteFile(foo, bar));
4141 
4142   EXPECT_FALSE(IsDirectoryEmpty(empty_dir));
4143 }
4144 
4145 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
4146 
TEST_F(FileUtilTest,SetNonBlocking)4147 TEST_F(FileUtilTest, SetNonBlocking) {
4148   const int kBogusFd = 99999;
4149   EXPECT_FALSE(SetNonBlocking(kBogusFd));
4150 
4151   FilePath path;
4152   ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &path));
4153   path = path.Append(FPL("file_util")).Append(FPL("original.txt"));
4154   ScopedFD fd(open(path.value().c_str(), O_RDONLY));
4155   ASSERT_GE(fd.get(), 0);
4156   EXPECT_TRUE(SetNonBlocking(fd.get()));
4157 }
4158 
TEST_F(FileUtilTest,SetCloseOnExec)4159 TEST_F(FileUtilTest, SetCloseOnExec) {
4160   const int kBogusFd = 99999;
4161   EXPECT_FALSE(SetCloseOnExec(kBogusFd));
4162 
4163   FilePath path;
4164   ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &path));
4165   path = path.Append(FPL("file_util")).Append(FPL("original.txt"));
4166   ScopedFD fd(open(path.value().c_str(), O_RDONLY));
4167   ASSERT_GE(fd.get(), 0);
4168   EXPECT_TRUE(SetCloseOnExec(fd.get()));
4169 }
4170 
4171 #endif
4172 
4173 #if BUILDFLAG(IS_MAC)
4174 
4175 // Testing VerifyPathControlledByAdmin() is hard, because there is no
4176 // way a test can make a file owned by root, or change file paths
4177 // at the root of the file system.  VerifyPathControlledByAdmin()
4178 // is implemented as a call to VerifyPathControlledByUser, which gives
4179 // us the ability to test with paths under the test's temp directory,
4180 // using a user id we control.
4181 // Pull tests of VerifyPathControlledByUserTest() into a separate test class
4182 // with a common SetUp() method.
4183 class VerifyPathControlledByUserTest : public FileUtilTest {
4184  protected:
SetUp()4185   void SetUp() override {
4186     FileUtilTest::SetUp();
4187 
4188     // Create a basic structure used by each test.
4189     // base_dir_
4190     //  |-> sub_dir_
4191     //       |-> text_file_
4192 
4193     base_dir_ = temp_dir_.GetPath().AppendASCII("base_dir");
4194     ASSERT_TRUE(CreateDirectory(base_dir_));
4195 
4196     sub_dir_ = base_dir_.AppendASCII("sub_dir");
4197     ASSERT_TRUE(CreateDirectory(sub_dir_));
4198 
4199     text_file_ = sub_dir_.AppendASCII("file.txt");
4200     CreateTextFile(text_file_, L"This text file has some text in it.");
4201 
4202     // Get the user and group files are created with from |base_dir_|.
4203     stat_wrapper_t stat_buf;
4204     ASSERT_EQ(0, File::Stat(base_dir_.value().c_str(), &stat_buf));
4205     uid_ = stat_buf.st_uid;
4206     ok_gids_.insert(stat_buf.st_gid);
4207     bad_gids_.insert(stat_buf.st_gid + 1);
4208 
4209     ASSERT_EQ(uid_, getuid());  // This process should be the owner.
4210 
4211     // To ensure that umask settings do not cause the initial state
4212     // of permissions to be different from what we expect, explicitly
4213     // set permissions on the directories we create.
4214     // Make all files and directories non-world-writable.
4215 
4216     // Users and group can read, write, traverse
4217     int enabled_permissions =
4218         FILE_PERMISSION_USER_MASK | FILE_PERMISSION_GROUP_MASK;
4219     // Other users can't read, write, traverse
4220     int disabled_permissions = FILE_PERMISSION_OTHERS_MASK;
4221 
4222     ASSERT_NO_FATAL_FAILURE(
4223         ChangePosixFilePermissions(
4224             base_dir_, enabled_permissions, disabled_permissions));
4225     ASSERT_NO_FATAL_FAILURE(
4226         ChangePosixFilePermissions(
4227             sub_dir_, enabled_permissions, disabled_permissions));
4228   }
4229 
4230   FilePath base_dir_;
4231   FilePath sub_dir_;
4232   FilePath text_file_;
4233   uid_t uid_;
4234 
4235   std::set<gid_t> ok_gids_;
4236   std::set<gid_t> bad_gids_;
4237 };
4238 
TEST_F(VerifyPathControlledByUserTest,BadPaths)4239 TEST_F(VerifyPathControlledByUserTest, BadPaths) {
4240   // File does not exist.
4241   FilePath does_not_exist = base_dir_.AppendASCII("does")
4242                                      .AppendASCII("not")
4243                                      .AppendASCII("exist");
4244   EXPECT_FALSE(
4245       VerifyPathControlledByUser(base_dir_, does_not_exist, uid_, ok_gids_));
4246 
4247   // |base| not a subpath of |path|.
4248   EXPECT_FALSE(VerifyPathControlledByUser(sub_dir_, base_dir_, uid_, ok_gids_));
4249 
4250   // An empty base path will fail to be a prefix for any path.
4251   FilePath empty;
4252   EXPECT_FALSE(VerifyPathControlledByUser(empty, base_dir_, uid_, ok_gids_));
4253 
4254   // Finding that a bad call fails proves nothing unless a good call succeeds.
4255   EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
4256 }
4257 
TEST_F(VerifyPathControlledByUserTest,Symlinks)4258 TEST_F(VerifyPathControlledByUserTest, Symlinks) {
4259   // Symlinks in the path should cause failure.
4260 
4261   // Symlink to the file at the end of the path.
4262   FilePath file_link =  base_dir_.AppendASCII("file_link");
4263   ASSERT_TRUE(CreateSymbolicLink(text_file_, file_link))
4264       << "Failed to create symlink.";
4265 
4266   EXPECT_FALSE(
4267       VerifyPathControlledByUser(base_dir_, file_link, uid_, ok_gids_));
4268   EXPECT_FALSE(
4269       VerifyPathControlledByUser(file_link, file_link, uid_, ok_gids_));
4270 
4271   // Symlink from one directory to another within the path.
4272   FilePath link_to_sub_dir =  base_dir_.AppendASCII("link_to_sub_dir");
4273   ASSERT_TRUE(CreateSymbolicLink(sub_dir_, link_to_sub_dir))
4274     << "Failed to create symlink.";
4275 
4276   FilePath file_path_with_link = link_to_sub_dir.AppendASCII("file.txt");
4277   ASSERT_TRUE(PathExists(file_path_with_link));
4278 
4279   EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, file_path_with_link, uid_,
4280                                           ok_gids_));
4281 
4282   EXPECT_FALSE(VerifyPathControlledByUser(link_to_sub_dir, file_path_with_link,
4283                                           uid_, ok_gids_));
4284 
4285   // Symlinks in parents of base path are allowed.
4286   EXPECT_TRUE(VerifyPathControlledByUser(file_path_with_link,
4287                                          file_path_with_link, uid_, ok_gids_));
4288 }
4289 
TEST_F(VerifyPathControlledByUserTest,OwnershipChecks)4290 TEST_F(VerifyPathControlledByUserTest, OwnershipChecks) {
4291   // Get a uid that is not the uid of files we create.
4292   uid_t bad_uid = uid_ + 1;
4293 
4294   // Make all files and directories non-world-writable.
4295   ASSERT_NO_FATAL_FAILURE(
4296       ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
4297   ASSERT_NO_FATAL_FAILURE(
4298       ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
4299   ASSERT_NO_FATAL_FAILURE(
4300       ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
4301 
4302   // We control these paths.
4303   EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
4304   EXPECT_TRUE(
4305       VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
4306   EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
4307 
4308   // Another user does not control these paths.
4309   EXPECT_FALSE(
4310       VerifyPathControlledByUser(base_dir_, sub_dir_, bad_uid, ok_gids_));
4311   EXPECT_FALSE(
4312       VerifyPathControlledByUser(base_dir_, text_file_, bad_uid, ok_gids_));
4313   EXPECT_FALSE(
4314       VerifyPathControlledByUser(sub_dir_, text_file_, bad_uid, ok_gids_));
4315 
4316   // Another group does not control the paths.
4317   EXPECT_FALSE(
4318       VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, bad_gids_));
4319   EXPECT_FALSE(
4320       VerifyPathControlledByUser(base_dir_, text_file_, uid_, bad_gids_));
4321   EXPECT_FALSE(
4322       VerifyPathControlledByUser(sub_dir_, text_file_, uid_, bad_gids_));
4323 }
4324 
TEST_F(VerifyPathControlledByUserTest,GroupWriteTest)4325 TEST_F(VerifyPathControlledByUserTest, GroupWriteTest) {
4326   // Make all files and directories writable only by their owner.
4327   ASSERT_NO_FATAL_FAILURE(
4328       ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH|S_IWGRP));
4329   ASSERT_NO_FATAL_FAILURE(
4330       ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH|S_IWGRP));
4331   ASSERT_NO_FATAL_FAILURE(
4332       ChangePosixFilePermissions(text_file_, 0u, S_IWOTH|S_IWGRP));
4333 
4334   // Any group is okay because the path is not group-writable.
4335   EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
4336   EXPECT_TRUE(
4337       VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
4338   EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
4339 
4340   EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, bad_gids_));
4341   EXPECT_TRUE(
4342       VerifyPathControlledByUser(base_dir_, text_file_, uid_, bad_gids_));
4343   EXPECT_TRUE(
4344       VerifyPathControlledByUser(sub_dir_, text_file_, uid_, bad_gids_));
4345 
4346   // No group is okay, because we don't check the group
4347   // if no group can write.
4348   std::set<gid_t> no_gids;  // Empty set of gids.
4349   EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, no_gids));
4350   EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, text_file_, uid_, no_gids));
4351   EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, no_gids));
4352 
4353   // Make all files and directories writable by their group.
4354   ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(base_dir_, S_IWGRP, 0u));
4355   ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(sub_dir_, S_IWGRP, 0u));
4356   ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(text_file_, S_IWGRP, 0u));
4357 
4358   // Now |ok_gids_| works, but |bad_gids_| fails.
4359   EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
4360   EXPECT_TRUE(
4361       VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
4362   EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
4363 
4364   EXPECT_FALSE(
4365       VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, bad_gids_));
4366   EXPECT_FALSE(
4367       VerifyPathControlledByUser(base_dir_, text_file_, uid_, bad_gids_));
4368   EXPECT_FALSE(
4369       VerifyPathControlledByUser(sub_dir_, text_file_, uid_, bad_gids_));
4370 
4371   // Because any group in the group set is allowed,
4372   // the union of good and bad gids passes.
4373 
4374   std::set<gid_t> multiple_gids;
4375   std::set_union(
4376       ok_gids_.begin(), ok_gids_.end(),
4377       bad_gids_.begin(), bad_gids_.end(),
4378       std::inserter(multiple_gids, multiple_gids.begin()));
4379 
4380   EXPECT_TRUE(
4381       VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, multiple_gids));
4382   EXPECT_TRUE(
4383       VerifyPathControlledByUser(base_dir_, text_file_, uid_, multiple_gids));
4384   EXPECT_TRUE(
4385       VerifyPathControlledByUser(sub_dir_, text_file_, uid_, multiple_gids));
4386 }
4387 
TEST_F(VerifyPathControlledByUserTest,WriteBitChecks)4388 TEST_F(VerifyPathControlledByUserTest, WriteBitChecks) {
4389   // Make all files and directories non-world-writable.
4390   ASSERT_NO_FATAL_FAILURE(
4391       ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
4392   ASSERT_NO_FATAL_FAILURE(
4393       ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
4394   ASSERT_NO_FATAL_FAILURE(
4395       ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
4396 
4397   // Initialy, we control all parts of the path.
4398   EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
4399   EXPECT_TRUE(
4400       VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
4401   EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
4402 
4403   // Make base_dir_ world-writable.
4404   ASSERT_NO_FATAL_FAILURE(
4405       ChangePosixFilePermissions(base_dir_, S_IWOTH, 0u));
4406   EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
4407   EXPECT_FALSE(
4408       VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
4409   EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
4410 
4411   // Make sub_dir_ world writable.
4412   ASSERT_NO_FATAL_FAILURE(
4413       ChangePosixFilePermissions(sub_dir_, S_IWOTH, 0u));
4414   EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
4415   EXPECT_FALSE(
4416       VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
4417   EXPECT_FALSE(
4418       VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
4419 
4420   // Make text_file_ world writable.
4421   ASSERT_NO_FATAL_FAILURE(
4422       ChangePosixFilePermissions(text_file_, S_IWOTH, 0u));
4423   EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
4424   EXPECT_FALSE(
4425       VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
4426   EXPECT_FALSE(
4427       VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
4428 
4429   // Make sub_dir_ non-world writable.
4430   ASSERT_NO_FATAL_FAILURE(
4431       ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
4432   EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
4433   EXPECT_FALSE(
4434       VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
4435   EXPECT_FALSE(
4436       VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
4437 
4438   // Make base_dir_ non-world-writable.
4439   ASSERT_NO_FATAL_FAILURE(
4440       ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
4441   EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
4442   EXPECT_FALSE(
4443       VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
4444   EXPECT_FALSE(
4445       VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
4446 
4447   // Back to the initial state: Nothing is writable, so every path
4448   // should pass.
4449   ASSERT_NO_FATAL_FAILURE(
4450       ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
4451   EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
4452   EXPECT_TRUE(
4453       VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
4454   EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
4455 }
4456 
4457 #endif  // BUILDFLAG(IS_MAC)
4458 
4459 // Flaky test: crbug/1054637
4460 #if BUILDFLAG(IS_ANDROID)
TEST_F(FileUtilTest,DISABLED_ValidContentUriTest)4461 TEST_F(FileUtilTest, DISABLED_ValidContentUriTest) {
4462   // Get the test image path.
4463   FilePath data_dir;
4464   ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
4465   data_dir = data_dir.AppendASCII("file_util");
4466   ASSERT_TRUE(PathExists(data_dir));
4467   FilePath image_file = data_dir.Append(FILE_PATH_LITERAL("red.png"));
4468   int64_t image_size;
4469   GetFileSize(image_file, &image_size);
4470   ASSERT_GT(image_size, 0);
4471 
4472   // Insert the image into MediaStore. MediaStore will do some conversions, and
4473   // return the content URI.
4474   FilePath path = InsertImageIntoMediaStore(image_file);
4475   EXPECT_TRUE(path.IsContentUri());
4476   EXPECT_TRUE(PathExists(path));
4477   // The file size may not equal to the input image as MediaStore may convert
4478   // the image.
4479   int64_t content_uri_size;
4480   GetFileSize(path, &content_uri_size);
4481   EXPECT_EQ(image_size, content_uri_size);
4482 
4483   // We should be able to read the file.
4484   File file = OpenContentUriForRead(path);
4485   EXPECT_TRUE(file.IsValid());
4486   auto buffer = std::make_unique<char[]>(image_size);
4487   EXPECT_TRUE(file.ReadAtCurrentPos(buffer.get(), image_size));
4488 }
4489 
TEST_F(FileUtilTest,NonExistentContentUriTest)4490 TEST_F(FileUtilTest, NonExistentContentUriTest) {
4491   FilePath path("content://foo.bar");
4492   EXPECT_TRUE(path.IsContentUri());
4493   EXPECT_FALSE(PathExists(path));
4494   // Size should be smaller than 0.
4495   int64_t size;
4496   EXPECT_FALSE(GetFileSize(path, &size));
4497 
4498   // We should not be able to read the file.
4499   File file = OpenContentUriForRead(path);
4500   EXPECT_FALSE(file.IsValid());
4501 }
4502 #endif
4503 
TEST_F(FileUtilTest,GetUniquePathNumberNoFile)4504 TEST_F(FileUtilTest, GetUniquePathNumberNoFile) {
4505   // This file does not exist.
4506   const FilePath some_file = temp_dir_.GetPath().Append(FPL("SomeFile.txt"));
4507 
4508   // The path is unique as-is.
4509   EXPECT_EQ(GetUniquePathNumber(some_file), 0);
4510 }
4511 
TEST_F(FileUtilTest,GetUniquePathNumberFileExists)4512 TEST_F(FileUtilTest, GetUniquePathNumberFileExists) {
4513   // Create a file with the desired path.
4514   const FilePath some_file = temp_dir_.GetPath().Append(FPL("SomeFile.txt"));
4515   ASSERT_TRUE(File(some_file, File::FLAG_CREATE | File::FLAG_WRITE).IsValid());
4516 
4517   // The file exists, so the number 1 is needed to make it unique.
4518   EXPECT_EQ(GetUniquePathNumber(some_file), 1);
4519 }
4520 
TEST_F(FileUtilTest,GetUniquePathNumberFilesExist)4521 TEST_F(FileUtilTest, GetUniquePathNumberFilesExist) {
4522   // Create a file with the desired path and with it suffixed with " (1)"
4523   const FilePath some_file = temp_dir_.GetPath().Append(FPL("SomeFile.txt"));
4524   ASSERT_TRUE(File(some_file, File::FLAG_CREATE | File::FLAG_WRITE).IsValid());
4525   const FilePath some_file_one =
4526       temp_dir_.GetPath().Append(FPL("SomeFile (1).txt"));
4527   ASSERT_TRUE(
4528       File(some_file_one, File::FLAG_CREATE | File::FLAG_WRITE).IsValid());
4529 
4530   // This time the number 2 is needed to make it unique.
4531   EXPECT_EQ(GetUniquePathNumber(some_file), 2);
4532 }
4533 
TEST_F(FileUtilTest,GetUniquePathNumberTooManyFiles)4534 TEST_F(FileUtilTest, GetUniquePathNumberTooManyFiles) {
4535   // Create a file with the desired path.
4536   const FilePath some_file = temp_dir_.GetPath().Append(FPL("SomeFile.txt"));
4537   ASSERT_TRUE(File(some_file, File::FLAG_CREATE | File::FLAG_WRITE).IsValid());
4538 
4539   // Now create 100 collisions.
4540   for (int i = 1; i <= kMaxUniqueFiles; ++i) {
4541     ASSERT_EQ(GetUniquePathNumber(some_file), i);
4542     ASSERT_TRUE(File(temp_dir_.GetPath().AppendASCII(
4543                          StringPrintf("SomeFile (%d).txt", i)),
4544                      File::FLAG_CREATE | File::FLAG_WRITE)
4545                     .IsValid());
4546   }
4547 
4548   // Verify that the limit has been reached.
4549   EXPECT_EQ(GetUniquePathNumber(some_file), -1);
4550 }
4551 
4552 #if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING) && \
4553     defined(ARCH_CPU_32_BITS)
4554 // TODO(crbug.com/327582285): Re-enable these tests. They may be failing due to
4555 // prefetching failing under memory pressure.
4556 #define FLAKY_327582285 1
4557 #endif
4558 
4559 #if defined(FLAKY_327582285)
4560 #define MAYBE_PreReadFileExistingFileNoSize \
4561   DISABLED_PreReadFileExistingFileNoSize
4562 #else
4563 #define MAYBE_PreReadFileExistingFileNoSize PreReadFileExistingFileNoSize
4564 #endif
TEST_F(FileUtilTest,MAYBE_PreReadFileExistingFileNoSize)4565 TEST_F(FileUtilTest, MAYBE_PreReadFileExistingFileNoSize) {
4566   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
4567   CreateTextFile(text_file, bogus_content);
4568 
4569   EXPECT_TRUE(
4570       PreReadFile(text_file, /*is_executable=*/false, /*sequential=*/false));
4571 }
4572 
4573 #if defined(FLAKY_327582285)
4574 #define MAYBE_PreReadFileExistingFileExactSize \
4575   DISABLED_PreReadFileExistingFileExactSize
4576 #else
4577 #define MAYBE_PreReadFileExistingFileExactSize PreReadFileExistingFileExactSize
4578 #endif
TEST_F(FileUtilTest,MAYBE_PreReadFileExistingFileExactSize)4579 TEST_F(FileUtilTest, MAYBE_PreReadFileExistingFileExactSize) {
4580   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
4581   CreateTextFile(text_file, bogus_content);
4582 
4583   EXPECT_TRUE(PreReadFile(text_file, /*is_executable=*/false,
4584                           /*sequential=*/false, std::size(bogus_content)));
4585 }
4586 
4587 #if defined(FLAKY_327582285)
4588 #define MAYBE_PreReadFileExistingFileOverSized \
4589   DISABLED_PreReadFileExistingFileOverSized
4590 #else
4591 #define MAYBE_PreReadFileExistingFileOverSized PreReadFileExistingFileOverSized
4592 #endif
TEST_F(FileUtilTest,MAYBE_PreReadFileExistingFileOverSized)4593 TEST_F(FileUtilTest, MAYBE_PreReadFileExistingFileOverSized) {
4594   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
4595   CreateTextFile(text_file, bogus_content);
4596 
4597   EXPECT_TRUE(PreReadFile(text_file, /*is_executable=*/false,
4598                           /*sequential=*/false, std::size(bogus_content) * 2));
4599 }
4600 
4601 #if defined(FLAKY_327582285)
4602 #define MAYBE_PreReadFileExistingFileUnderSized \
4603   DISABLED_PreReadFileExistingFileUnderSized
4604 #else
4605 #define MAYBE_PreReadFileExistingFileUnderSized \
4606   PreReadFileExistingFileUnderSized
4607 #endif
TEST_F(FileUtilTest,MAYBE_PreReadFileExistingFileUnderSized)4608 TEST_F(FileUtilTest, MAYBE_PreReadFileExistingFileUnderSized) {
4609   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
4610   CreateTextFile(text_file, bogus_content);
4611 
4612   EXPECT_TRUE(PreReadFile(text_file, /*is_executable=*/false,
4613                           /*sequential=*/false, std::size(bogus_content) / 2));
4614 }
4615 
TEST_F(FileUtilTest,PreReadFileExistingFileZeroSize)4616 TEST_F(FileUtilTest, PreReadFileExistingFileZeroSize) {
4617   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
4618   CreateTextFile(text_file, bogus_content);
4619 
4620   EXPECT_TRUE(PreReadFile(text_file, /*is_executable=*/false,
4621                           /*sequential=*/false, /*max_bytes=*/0));
4622 }
4623 
TEST_F(FileUtilTest,PreReadFileExistingEmptyFileNoSize)4624 TEST_F(FileUtilTest, PreReadFileExistingEmptyFileNoSize) {
4625   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
4626   CreateTextFile(text_file, L"");
4627   // The test just asserts that this doesn't crash. The Windows implementation
4628   // fails in this case, due to the base::MemoryMappedFile implementation and
4629   // the limitations of ::MapViewOfFile().
4630   PreReadFile(text_file, /*is_executable=*/false, /*sequential=*/false);
4631 }
4632 
TEST_F(FileUtilTest,PreReadFileExistingEmptyFileZeroSize)4633 TEST_F(FileUtilTest, PreReadFileExistingEmptyFileZeroSize) {
4634   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
4635   CreateTextFile(text_file, L"");
4636   EXPECT_TRUE(PreReadFile(text_file, /*is_executable=*/false,
4637                           /*sequential=*/false, /*max_bytes=*/0));
4638 }
4639 
TEST_F(FileUtilTest,PreReadFileInexistentFile)4640 TEST_F(FileUtilTest, PreReadFileInexistentFile) {
4641   FilePath inexistent_file = temp_dir_.GetPath().Append(FPL("inexistent_file"));
4642   EXPECT_FALSE(PreReadFile(inexistent_file, /*is_executable=*/false,
4643                            /*sequential=*/false));
4644 }
4645 
4646 #if defined(FLAKY_327582285)
4647 #define MAYBE_PreReadFileExecutable DISABLED_PreReadFileExecutable
4648 #else
4649 #define MAYBE_PreReadFileExecutable PreReadFileExecutable
4650 #endif
TEST_F(FileUtilTest,MAYBE_PreReadFileExecutable)4651 TEST_F(FileUtilTest, MAYBE_PreReadFileExecutable) {
4652   FilePath exe_data_dir;
4653   ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &exe_data_dir));
4654   exe_data_dir = exe_data_dir.Append(FPL("pe_image_reader"));
4655   ASSERT_TRUE(PathExists(exe_data_dir));
4656 
4657   // Load a sample executable and confirm that it was successfully prefetched.
4658   // `test_exe` is a Windows binary, which is fine in this case because only the
4659   // Windows implementation treats binaries differently from other files.
4660   const FilePath test_exe = exe_data_dir.Append(FPL("signed.exe"));
4661   EXPECT_TRUE(
4662       PreReadFile(test_exe, /*is_executable=*/true, /*sequential=*/false));
4663 }
4664 
4665 #if defined(FLAKY_327582285)
4666 #define MAYBE_PreReadFileWithSequentialAccess \
4667   DISABLED_PreReadFileWithSequentialAccess
4668 #else
4669 #define MAYBE_PreReadFileWithSequentialAccess PreReadFileWithSequentialAccess
4670 #endif
TEST_F(FileUtilTest,MAYBE_PreReadFileWithSequentialAccess)4671 TEST_F(FileUtilTest, MAYBE_PreReadFileWithSequentialAccess) {
4672   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
4673   CreateTextFile(text_file, bogus_content);
4674 
4675   EXPECT_TRUE(
4676       PreReadFile(text_file, /*is_executable=*/false, /*sequential=*/true));
4677 }
4678 
4679 #undef FLAKY_327582285
4680 
4681 // Test that temp files obtained racily are all unique (no interference between
4682 // threads). Mimics file operations in DoLaunchChildTestProcess() to rule out
4683 // thread-safety issues @ https://crbug.com/826408#c17.
TEST(FileUtilMultiThreadedTest,MultiThreadedTempFiles)4684 TEST(FileUtilMultiThreadedTest, MultiThreadedTempFiles) {
4685 #if BUILDFLAG(IS_FUCHSIA)
4686   // TODO(crbug.com/844416): Too slow to run on infra due to QEMU overhead.
4687   constexpr int kNumThreads = 8;
4688 #else
4689   constexpr int kNumThreads = 64;
4690 #endif
4691   constexpr int kNumWritesPerThread = 32;
4692 
4693   std::unique_ptr<Thread> threads[kNumThreads];
4694   for (auto& thread : threads) {
4695     thread = std::make_unique<Thread>("test worker");
4696     thread->Start();
4697   }
4698 
4699   // Wait until all threads are started for max parallelism.
4700   for (auto& thread : threads)
4701     thread->WaitUntilThreadStarted();
4702 
4703   const RepeatingClosure open_write_close_read = BindRepeating([]() {
4704     FilePath output_filename;
4705     ScopedFILE output_file(CreateAndOpenTemporaryStream(&output_filename));
4706     EXPECT_TRUE(output_file);
4707 
4708     const std::string content = Uuid::GenerateRandomV4().AsLowercaseString();
4709 #if BUILDFLAG(IS_WIN)
4710     HANDLE handle =
4711         reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(output_file.get())));
4712     DWORD bytes_written = 0;
4713     ::WriteFile(handle, content.c_str(), content.length(), &bytes_written,
4714                 NULL);
4715 #else
4716     size_t bytes_written =
4717         ::write(::fileno(output_file.get()), content.c_str(), content.length());
4718 #endif
4719     EXPECT_EQ(content.length(), bytes_written);
4720     ::fflush(output_file.get());
4721     output_file.reset();
4722 
4723     std::string output_file_contents;
4724     EXPECT_TRUE(ReadFileToString(output_filename, &output_file_contents))
4725         << output_filename;
4726 
4727     EXPECT_EQ(content, output_file_contents);
4728 
4729     DeleteFile(output_filename);
4730   });
4731 
4732   // Post tasks to each thread in a round-robin fashion to ensure as much
4733   // parallelism as possible.
4734   for (int i = 0; i < kNumWritesPerThread; ++i) {
4735     for (auto& thread : threads) {
4736       thread->task_runner()->PostTask(FROM_HERE, open_write_close_read);
4737     }
4738   }
4739 
4740   for (auto& thread : threads)
4741     thread->Stop();
4742 }
4743 
4744 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
4745 
TEST(ScopedFD,ScopedFDDoesClose)4746 TEST(ScopedFD, ScopedFDDoesClose) {
4747   int fds[2];
4748   char c = 0;
4749   ASSERT_EQ(0, pipe(fds));
4750   const int write_end = fds[1];
4751   ScopedFD read_end_closer(fds[0]);
4752   {
4753     ScopedFD write_end_closer(fds[1]);
4754   }
4755   // This is the only thread. This file descriptor should no longer be valid.
4756   int ret = close(write_end);
4757   EXPECT_EQ(-1, ret);
4758   EXPECT_EQ(EBADF, errno);
4759   // Make sure read(2) won't block.
4760   ASSERT_EQ(0, fcntl(fds[0], F_SETFL, O_NONBLOCK));
4761   // Reading the pipe should EOF.
4762   EXPECT_EQ(0, read(fds[0], &c, 1));
4763 }
4764 
4765 #if defined(GTEST_HAS_DEATH_TEST)
CloseWithScopedFD(int fd)4766 void CloseWithScopedFD(int fd) {
4767   ScopedFD fd_closer(fd);
4768 }
4769 #endif
4770 
TEST(ScopedFD,ScopedFDCrashesOnCloseFailure)4771 TEST(ScopedFD, ScopedFDCrashesOnCloseFailure) {
4772   int fds[2];
4773   ASSERT_EQ(0, pipe(fds));
4774   ScopedFD read_end_closer(fds[0]);
4775   EXPECT_EQ(0, IGNORE_EINTR(close(fds[1])));
4776 #if defined(GTEST_HAS_DEATH_TEST)
4777   // This is the only thread. This file descriptor should no longer be valid.
4778   // Trying to close it should crash. This is important for security.
4779   EXPECT_DEATH(CloseWithScopedFD(fds[1]), "");
4780 #endif
4781 }
4782 
4783 #endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
4784 
4785 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
TEST_F(FileUtilTest,CopyFileContentsWithSendfile)4786 TEST_F(FileUtilTest, CopyFileContentsWithSendfile) {
4787   // This test validates that sendfile(2) can be used to copy a file contents
4788   // and that it will honor the file offsets as CopyFileContents does.
4789   FilePath file_name_from = temp_dir_.GetPath().Append(
4790       FILE_PATH_LITERAL("copy_contents_file_in.txt"));
4791   FilePath file_name_to = temp_dir_.GetPath().Append(
4792       FILE_PATH_LITERAL("copy_contents_file_out.txt"));
4793 
4794   const std::wstring from_contents(L"0123456789ABCDEF");
4795   CreateTextFile(file_name_from, from_contents);
4796   ASSERT_TRUE(PathExists(file_name_from));
4797 
4798   const std::wstring to_contents(L"GHIJKL");
4799   CreateTextFile(file_name_to, to_contents);
4800   ASSERT_TRUE(PathExists(file_name_to));
4801 
4802   File from(file_name_from, File::FLAG_OPEN | File::FLAG_READ);
4803   ASSERT_TRUE(from.IsValid());
4804 
4805   File to(file_name_to, File::FLAG_OPEN | File::FLAG_WRITE);
4806   ASSERT_TRUE(to.IsValid());
4807 
4808   // See to the 1st byte in each file.
4809   ASSERT_EQ(from.Seek(File::Whence::FROM_BEGIN, 1), 1);
4810   ASSERT_EQ(to.Seek(File::Whence::FROM_BEGIN, 1), 1);
4811 
4812   bool retry_slow = false;
4813 
4814   // Given the test setup there should never be a sendfile(2) failure.
4815   ASSERT_TRUE(internal::CopyFileContentsWithSendfile(from, to, retry_slow));
4816   from.Close();
4817   to.Close();
4818 
4819   // Expect the output file contents to be: G123456789ABCDEF because both
4820   // file positions when we copied the file contents were at 1.
4821   EXPECT_EQ(L"G123456789ABCDEF", ReadTextFile(file_name_to));
4822 }
4823 
TEST_F(FileUtilTest,CopyFileContentsWithSendfileEmpty)4824 TEST_F(FileUtilTest, CopyFileContentsWithSendfileEmpty) {
4825   FilePath file_name_from = temp_dir_.GetPath().Append(
4826       FILE_PATH_LITERAL("copy_contents_file_in.txt"));
4827   FilePath file_name_to = temp_dir_.GetPath().Append(
4828       FILE_PATH_LITERAL("copy_contents_file_out.txt"));
4829 
4830   const std::wstring from_contents(L"");
4831   CreateTextFile(file_name_from, from_contents);
4832   ASSERT_TRUE(PathExists(file_name_from));
4833 
4834   const std::wstring to_contents(L"");
4835   CreateTextFile(file_name_to, to_contents);
4836   ASSERT_TRUE(PathExists(file_name_to));
4837 
4838   File from(file_name_from, File::FLAG_OPEN | File::FLAG_READ);
4839   ASSERT_TRUE(from.IsValid());
4840 
4841   File to(file_name_to, File::FLAG_OPEN | File::FLAG_WRITE);
4842   ASSERT_TRUE(to.IsValid());
4843 
4844   bool retry_slow = false;
4845 
4846   ASSERT_FALSE(internal::CopyFileContentsWithSendfile(from, to, retry_slow));
4847   ASSERT_TRUE(retry_slow);
4848 
4849   from.Close();
4850   to.Close();
4851 
4852   EXPECT_EQ(L"", ReadTextFile(file_name_to));
4853 }
4854 
TEST_F(FileUtilTest,CopyFileContentsWithSendfilePipe)4855 TEST_F(FileUtilTest, CopyFileContentsWithSendfilePipe) {
4856   FilePath file_name_to = temp_dir_.GetPath().Append(
4857       FILE_PATH_LITERAL("copy_contents_file_out.txt"));
4858 
4859   File to(file_name_to,
4860           File::FLAG_OPEN | File::FLAG_WRITE | File::FLAG_CREATE_ALWAYS);
4861   ASSERT_TRUE(to.IsValid());
4862 
4863   // This test validates that CopyFileContentsWithSendfile fails with a pipe and
4864   // retry_slow is set.
4865   int fd[2];
4866   ASSERT_EQ(pipe2(fd, O_CLOEXEC), 0);
4867 
4868   // For good measure write some data into the pipe.
4869   const char* buf = "hello world";
4870   ASSERT_EQ(write(fd[1], buf, sizeof(buf)), static_cast<int>(sizeof(buf)));
4871 
4872   // fd[0] refers to the read end of the pipe.
4873   bool retry_slow = false;
4874   base::PlatformFile pipe_read_end(fd[0]);
4875   base::File pipe_read(pipe_read_end);
4876   ASSERT_FALSE(
4877       internal::CopyFileContentsWithSendfile(pipe_read, to, retry_slow));
4878   ASSERT_TRUE(retry_slow);
4879 }
4880 
TEST_F(FileUtilTest,CopyFileContentsWithSendfileSocket)4881 TEST_F(FileUtilTest, CopyFileContentsWithSendfileSocket) {
4882   // This test validates that CopyFileContentsWithSendfile fails with a socket
4883   // and retry_slow is set.
4884   int sock[2];
4885   ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sock), 0);
4886 
4887   FilePath file_name_from = temp_dir_.GetPath().Append(
4888       FILE_PATH_LITERAL("copy_contents_file_in.txt"));
4889   FilePath file_name_to = temp_dir_.GetPath().Append(
4890       FILE_PATH_LITERAL("copy_contents_file_out.txt"));
4891   const std::wstring from_contents(L"0123456789ABCDEF");
4892   CreateTextFile(file_name_from, from_contents);
4893   ASSERT_TRUE(PathExists(file_name_from));
4894 
4895   File from(file_name_from, File::FLAG_OPEN | File::FLAG_READ);
4896   ASSERT_TRUE(from.IsValid());
4897 
4898   base::PlatformFile to_file(sock[0]);
4899   base::File to_sock(to_file);
4900 
4901   // Copying from a file to a socket will work.
4902   bool retry_slow = false;
4903   ASSERT_TRUE(
4904       internal::CopyFileContentsWithSendfile(from, to_sock, retry_slow));
4905 
4906   // But copying for a socket to a file will not.
4907   base::PlatformFile from_sock_file(sock[1]);
4908   base::File from_sock(from_sock_file);
4909 
4910   File to(file_name_to,
4911           File::FLAG_OPEN | File::FLAG_WRITE | File::FLAG_CREATE_ALWAYS);
4912   ASSERT_TRUE(to.IsValid());
4913   ASSERT_FALSE(
4914       internal::CopyFileContentsWithSendfile(from_sock, to, retry_slow));
4915   ASSERT_TRUE(retry_slow);
4916 }
4917 
TEST_F(FileUtilTest,CopyFileContentsWithSendfileSeqFile)4918 TEST_F(FileUtilTest, CopyFileContentsWithSendfileSeqFile) {
4919   // This test verifies the special case where we have a regular file with zero
4920   // length that might actually have contents (such as a seq_file).
4921   for (auto* const file : {"/proc/meminfo", "/proc/self/cmdline",
4922                            "/proc/self/environ", "/proc/self/auxv"}) {
4923     FilePath proc_file_from(file);
4924     File from(proc_file_from, File::FLAG_OPEN | File::FLAG_READ);
4925     ASSERT_TRUE(from.IsValid()) << "could not open " << file;
4926 
4927     FilePath file_name_to = temp_dir_.GetPath().Append(
4928         FILE_PATH_LITERAL("copy_contents_file_out.txt"));
4929     File to(file_name_to,
4930             File::FLAG_OPEN | File::FLAG_WRITE | File::FLAG_CREATE_ALWAYS);
4931     ASSERT_TRUE(to.IsValid());
4932 
4933     bool retry_slow = false;
4934     ASSERT_FALSE(internal::CopyFileContentsWithSendfile(from, to, retry_slow))
4935         << proc_file_from << " should have failed";
4936     ASSERT_TRUE(retry_slow)
4937         << "retry slow for " << proc_file_from << " should be set";
4938 
4939     // Now let's make sure we can copy it the "slow" way.
4940     ASSERT_TRUE(base::CopyFileContents(from, to));
4941     ASSERT_GT(to.GetLength(), 0);
4942     ASSERT_TRUE(base::DeleteFile(file_name_to));
4943   }
4944 }
4945 
4946 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
4947         // BUILDFLAG(IS_ANDROID)
4948 
4949 }  // namespace
4950 
4951 }  // namespace base
4952