Make all the files mapped in when running base_unittests read only.

This means no file can be opened for write during the test run.

Make CopyFileUnsafe() reset the RO bit on Windows.
Add a tests that confirms the current CopyFile() behavior:
- On Windows, CopyFile() copies the ACL but now strips the READONLY bit.
- On OSX, CopyFile() copies the ACL.
- On anything else, ACL is not copied.

Rationale:
On anything-but-Windows, deleting a file require write access on the directory.
On Windows, deleting a file require not having the RO bit on the file.
CopyFile() affects the file but not the directory.

On isolated testing, the read only bit will be set on the file being copied,
causing the test to fail to delete the files.

This has wide implications in the unit tests. CopyFile() is mostly (but not
exclusively) used in unit tests.

R=thakis@chromium.org, vadimsh@chromium.org
BUG=116251

Review URL: https://codereview.chromium.org/136693004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@244947 0039d316-1c4b-4281-b951-d872f2087c98


CrOS-Libchrome-Original-Commit: 87750624ea6b424e8f94c1066ae879705e6d554e
diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc
index 96e144d..fc62064 100644
--- a/base/file_util_unittest.cc
+++ b/base/file_util_unittest.cc
@@ -1398,6 +1398,60 @@
   EXPECT_TRUE(PathExists(dest_file2));
 }
 
+#if defined(OS_WIN) || defined(OS_POSIX)
+TEST_F(FileUtilTest, CopyFileACL) {
+  // While FileUtilTest.CopyFile asserts the content is correctly copied over,
+  // this test case asserts the access control bits are meeting expectations in
+  // CopyFileUnsafe().
+  FilePath src = temp_dir_.path().Append(FILE_PATH_LITERAL("src.txt"));
+  const std::wstring file_contents(L"Gooooooooooooooooooooogle");
+  CreateTextFile(src, file_contents);
+
+  // Set the source file to read-only.
+#if defined(OS_WIN)
+  // On Windows, it involves setting a bit.
+  DWORD attrs = GetFileAttributes(src.value().c_str());
+  ASSERT_NE(INVALID_FILE_ATTRIBUTES, attrs);
+  ASSERT_TRUE(SetFileAttributes(
+      src.value().c_str(), attrs | FILE_ATTRIBUTE_READONLY));
+  attrs = GetFileAttributes(src.value().c_str());
+  // Files in the temporary directory should not be indexed ever. If this
+  // assumption change, fix this unit test accordingly.
+  DWORD expected = (FILE_ATTRIBUTE_NOT_CONTENT_INDEXED |
+                    FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY);
+  ASSERT_EQ(expected, attrs);
+#else
+  // On all other platforms, it involves removing the write bit.
+  EXPECT_TRUE(SetPosixFilePermissions(src, 0400));
+#endif
+
+  // Copy the file.
+  FilePath dst = temp_dir_.path().Append(FILE_PATH_LITERAL("dst.txt"));
+  ASSERT_TRUE(CopyFile(src, dst));
+  EXPECT_EQ(file_contents, ReadTextFile(dst));
+
+#if defined(OS_WIN)
+  // While the source file had RO bit set, the copied file doesn't. Other file
+  // modes are copied.
+  attrs = GetFileAttributes(src.value().c_str());
+  ASSERT_EQ(expected, attrs);
+  expected = FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_ARCHIVE;
+  attrs = GetFileAttributes(dst.value().c_str());
+  ASSERT_EQ(expected, attrs);
+#elif defined(OS_MACOSX)
+  // On OSX, file mode is copied.
+  int mode = 0;
+  EXPECT_TRUE(GetPosixFilePermissions(dst, &mode));
+  EXPECT_EQ(0400, mode & 0600);
+#else
+  // On other POSIX, file mode is not copied.
+  int mode = 0;
+  EXPECT_TRUE(GetPosixFilePermissions(dst, &mode));
+  EXPECT_EQ(0600, mode & 0600);
+#endif
+}
+#endif  // defined(OS_WIN) || defined(OS_POSIX)
+
 // file_util winds up using autoreleased objects on the Mac, so this needs
 // to be a PlatformTest.
 typedef PlatformTest ReadOnlyFileUtilTest;